Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
*.pyc
.codex/
.claude/
2 changes: 2 additions & 0 deletions polygon_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@
Stage,
Asset,
)

__version__ = "1.0.1"
164 changes: 158 additions & 6 deletions polygon_api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class Polygon:
_PROBLEM_SAVE_TEST = 'problem.saveTest'
_PROBLEM_ENABLE_GROUPS = 'problem.enableGroups'
_PROBLEM_ENABLE_POINTS = 'problem.enablePoints'
_PROBLEM_SET_TEST_GROUP = 'problem.setTestGroup'
_PROBLEM_VIEW_TEST_GROUP = 'problem.viewTestGroup'
_PROBLEM_SAVE_TEST_GROUP = 'problem.saveTestGroup'
_PROBLEM_VIEW_TAGS = 'problem.viewTags'
Expand All @@ -53,6 +54,9 @@ class Polygon:
_PROBLEM_SAVE_GENERAL_DESCRIPTION = 'problem.saveGeneralDescription'
_PROBLEM_VIEW_GENERAL_TUTORIAL = 'problem.viewGeneralTutorial'
_PROBLEM_SAVE_GENERAL_TUTORIAL = 'problem.saveGeneralTutorial'
_PROBLEM_BUILD_PACKAGE = 'problem.buildPackage'
_PROBLEM_PACKAGES = 'problem.packages'
_PROBLEM_PACKAGE = 'problem.package'

def __init__(self, api_url, api_key, api_secret):
self.request_config = RequestConfig(api_url, api_key, api_secret)
Expand Down Expand Up @@ -283,6 +287,44 @@ def problem_enable_points(self, problem_id, enable):
)
return response.result

def problem_set_test_group(self, problem_id, testset, test_group, test_index=None, test_indices=None):
"""
"""
if isinstance(test_indices, list):
test_indices = ",".join(map(str, test_indices))
response = self._request_ok_or_raise(
self._PROBLEM_SET_TEST_GROUP,
args={
'problemId': problem_id,
'testset': testset,
'testGroup': test_group,
'testIndex': test_index,
'testIndices': test_indices,
},
)
return response.result

def problem_script(self, problem_id, testset):
response = self._request_ok_or_raise(
self._PROBLEM_SCRIPT,
args={
'problemId': problem_id,
'testset': testset,
},
)
return response.result

def problem_save_script(self, problem_id, testset, source):
response = self._request_ok_or_raise(
self._PROBLEM_SAVE_SCRIPT,
args={
'problemId': problem_id,
'testset': testset,
'source': source,
}
)
return response.result

def problem_save_test(self, problem_id, testset, test_index, test_input, test_group=None, test_points=None,
test_description=None, test_use_in_statements=None, test_input_for_statements=None,
test_output_for_statements=None, verify_input_output_for_statements=None,
Expand Down Expand Up @@ -337,6 +379,28 @@ def problem_tests(self, problem_id, testset, no_inputs=None):
)
return [Test.from_json(self, problem_id, testset, js) for js in response.result]

def problem_test_input(self, problem_id, testset, test_index):
response = self._request_raw(
self._PROBLEM_TEST_INPUT,
args={
'problemId': problem_id,
'testset': testset,
'testIndex': test_index,
}
)
return response

def problem_test_answer(self, problem_id, testset, test_index):
response = self._request_raw(
self._PROBLEM_TEST_ANSWER,
args={
'problemId': problem_id,
'testset': testset,
'testIndex': test_index,
}
)
return response

def problem_save_test_group(self, problem_id, testset, group, points_policy=None, feedback_policy=None,
dependencies=None):
if isinstance(dependencies, list):
Expand Down Expand Up @@ -393,7 +457,8 @@ def problem_view_solution(self, problem_id, name):
)
return response

def problem_save_file(self, problem_id, type, name, file, source_type=None, resource_advanced_properties=None):
def problem_save_file(self, problem_id, type, name, file, source_type=None, resource_advanced_properties=None,
check_existing=None):
stages = None if resource_advanced_properties is None or resource_advanced_properties.stages is None else \
';'.join(map(str, resource_advanced_properties.stages))
assets = None if resource_advanced_properties is None or resource_advanced_properties.assets is None else \
Expand All @@ -409,6 +474,7 @@ def problem_save_file(self, problem_id, type, name, file, source_type=None, reso
'forTypes': None if resource_advanced_properties is None else resource_advanced_properties.for_types,
'stages': stages,
'assets': assets,
'checkExisting': check_existing,
}
)
return response.result
Expand Down Expand Up @@ -484,6 +550,36 @@ def problem_set_interactor(self, problem_id, interactor):
)
return response.result

def problem_packages(self, problem_id):
response = self._request_ok_or_raise(
self._PROBLEM_PACKAGES,
args={
'problemId': problem_id,
},
)
return [Package.from_json(package) for package in response.result]

def problem_package(self, problem_id, package_id, type=None):
return self._request_raw(
self._PROBLEM_PACKAGE,
args={
'problemId': problem_id,
'packageId': package_id,
'type': type,
},
)

def problem_build_package(self, problem_id, full, verify):
response = self._request_ok_or_raise(
self._PROBLEM_BUILD_PACKAGE,
args={
'problemId': problem_id,
'full': full,
'verify': verify,
},
)
return response.result

def contest_problems(self, contest_id):
"""
"""
Expand Down Expand Up @@ -610,6 +706,15 @@ def enable_groups(self, testset, enable):
def enable_points(self, enable):
return self._polygon.problem_enable_points(self.id, enable)

def set_test_group(self, testset, test_group, test_index=None, test_indices=None):
return self._polygon.problem_set_test_group(self.id, testset, test_group, test_index, test_indices)

def script(self, testset):
return self._polygon.problem_script(self.id, testset)

def save_script(self, testset, source):
return self._polygon.problem_save_script(self.id, testset, source)

def save_test(self, testset, test_index, test_input, test_group=None, test_points=None, test_description=None,
test_use_in_statements=None, test_input_for_statements=None, test_output_for_statements=None,
verify_input_output_for_statements=None, check_existing=None):
Expand All @@ -621,6 +726,12 @@ def save_test(self, testset, test_index, test_input, test_group=None, test_point
def tests(self, testset, no_inputs=None):
return self._polygon.problem_tests(self.id, testset, no_inputs)

def test_input(self, testset, test_index):
return self._polygon.problem_test_input(self.id, testset, test_index)

def test_answer(self, testset, test_index):
return self._polygon.problem_test_answer(self.id, testset, test_index)

def save_test_group(self, testset, group, points_policy=None, feedback_policy=None, dependencies=None):
return self._polygon.problem_save_test_group(self.id, testset, group,
points_policy, feedback_policy, dependencies)
Expand All @@ -634,8 +745,9 @@ def view_file(self, type, name):
def view_solution(self, name):
return self._polygon.problem_view_solution(self.id, name)

def save_file(self, type, name, file, source_type=None, resource_advanced_properties=None):
return self._polygon.problem_save_file(self.id, type, name, file, source_type, resource_advanced_properties)
def save_file(self, type, name, file, source_type=None, resource_advanced_properties=None, check_existing=None):
return self._polygon.problem_save_file(self.id, type, name, file, source_type,
resource_advanced_properties, check_existing)

def save_solution(self, name, file, source_type, tag, check_existing=None):
return self._polygon.problem_save_solution(self.id, name, file, source_type, tag, check_existing)
Expand Down Expand Up @@ -673,6 +785,15 @@ def files_source(self):
def files_aux(self):
return self.files()[FileType.AUX]

def packages(self):
return self._polygon.problem_packages(self.id)

def package(self, packageId, type=None):
return self._polygon.problem_package(self.id, packageId, type)

def build_package(self, full, verify):
return self._polygon.problem_build_package(self.id, full, verify)


class ProblemInfo:
"""
Expand Down Expand Up @@ -713,8 +834,8 @@ class Test:
_SCRIPT_LINE = "scriptLine"
_GROUP = "group"
_POINTS = "points"
_INPUT_FOR_STATEMENTS = "inputForStatements"
_OUTPUT_FOR_STATEMENTS = "outputForStatements"
_INPUT_FOR_STATEMENTS = "inputForStatement"
_OUTPUT_FOR_STATEMENTS = "outputForStatement"
_VERIFY_INPUT_OUTPUT_FOR_STATEMENTS = "verifyInputOutputForStatements"

@classmethod
Expand Down Expand Up @@ -927,6 +1048,37 @@ def __init__(self, name, modification_time_seconds, length, source_type, resourc
self.resource_advanced_properties = resource_advanced_properties


class Package:
"""
Object: representing Polygon package
"""
_ID = "id"
_REVISION = "revision"
_CREATION_TIME_SECONDS = "creationTimeSeconds"
_STATE = "state"
_COMMENT = "comment"
_TYPE = "type"

@classmethod
def from_json(cls, file_json):
return cls(
id=file_json[Package._ID],
revision=file_json[Package._REVISION],
creation_time_seconds=file_json[Package._CREATION_TIME_SECONDS],
state=file_json[Package._STATE],
comment=file_json[Package._COMMENT],
type=file_json.get(Package._TYPE, None)
)

def __init__(self, id, revision, creation_time_seconds, state, comment, type):
self.id = id
self.revision = revision
self.creation_time_seconds = creation_time_seconds
self.state = state
self.comment = comment
self.type = type


class ResourceAdvancedProperties:
"""
"""
Expand Down Expand Up @@ -1020,7 +1172,7 @@ def issue_raw(self):
response.raise_for_status()
except requests.exceptions.HTTPError as exc:
raise HTTPRequestFailedException(f'Method {self.method_name} returned HTTP code {response.status_code}') from exc
return response.text
return response.content

def get_api_signature(self, args, api_secret):
rand_bit = Request._value_to_utf8_bytes(''.join(
Expand Down