Skip to content

Commit 1ee7d37

Browse files
Merge pull request #32 from mishaschwartz/0.2.1
v0.2.1
2 parents fda51a2 + 2bd3be6 commit 1ee7d37

File tree

4 files changed

+301
-1
lines changed

4 files changed

+301
-1
lines changed

Changelog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Changelog
22

3+
## [v0.2.1]
4+
- Added new methods for managing starter files (#29)
5+
36
## [v0.2.0]
47
- Added new methods for adding and removing extra marks (#15)
58
- Rewrite everything to use the requests library (#26)

markusapi/markusapi.py

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,3 +475,143 @@ def get_test_files(self, assignment_id: int) -> requests.Response:
475475
the assignment with id <assignment_id>.
476476
"""
477477
return requests.get(self._url(f"assignments/{assignment_id}/test_files"), headers=self._auth_header)
478+
479+
@parse_response("json")
480+
def get_starter_file_entries(self, assignment_id: int, starter_file_group_id: int) -> requests.Response:
481+
"""
482+
Return the name of all entries for a given starter file group. Entries are file or directory names.
483+
"""
484+
return requests.get(
485+
self._url(f"assignments/{assignment_id}/starter_file_groups/{starter_file_group_id}/entries"),
486+
headers=self._auth_header,
487+
)
488+
489+
@parse_response("json")
490+
def create_starter_file(
491+
self, assignment_id: int, starter_file_group_id: int, file_path: str, contents: Union[str, bytes]
492+
) -> requests.Response:
493+
"""
494+
Upload a starter file to the starter file group with id=<starter_file_group_id> for assignment with
495+
id=<assignment_id>. The file_path should be a relative path from the starter file group's root directory.
496+
"""
497+
files = {"file_content": (file_path, contents)}
498+
params = {"filename": file_path}
499+
return requests.post(
500+
self._url(f"assignments/{assignment_id}/starter_file_groups/{starter_file_group_id}/create_file"),
501+
params=params,
502+
files=files,
503+
headers=self._auth_header,
504+
)
505+
506+
@parse_response("json")
507+
def create_starter_folder(
508+
self, assignment_id: int, starter_file_group_id: int, folder_path: str
509+
) -> requests.Response:
510+
"""
511+
Create a folder for the the starter file group with id=<starter_file_group_id> for assignment with
512+
id=<assignment_id>. The file_path should be a relative path from the starter file group's root directory.
513+
"""
514+
params = {"folder_path": folder_path}
515+
return requests.post(
516+
self._url(f"assignments/{assignment_id}/starter_file_groups/{starter_file_group_id}/create_folder"),
517+
params=params,
518+
headers=self._auth_header,
519+
)
520+
521+
@parse_response("json")
522+
def remove_starter_file(self, assignment_id: int, starter_file_group_id: int, file_path: str) -> requests.Response:
523+
"""
524+
Remove a starter file from the starter file group with id=<starter_file_group_id> for assignment with
525+
id=<assignment_id>. The file_path should be a relative path from the starter file group's root directory.
526+
"""
527+
params = {"filename": file_path}
528+
return requests.delete(
529+
self._url(f"assignments/{assignment_id}/starter_file_groups/{starter_file_group_id}/remove_file"),
530+
params=params,
531+
headers=self._auth_header,
532+
)
533+
534+
@parse_response("json")
535+
def remove_starter_folder(
536+
self, assignment_id: int, starter_file_group_id: int, folder_path: str
537+
) -> requests.Response:
538+
"""
539+
Remove a folder from the starter file group with id=<starter_file_group_id> for assignment with
540+
id=<assignment_id>. The file_path should be a relative path from the starter file group's root directory.
541+
"""
542+
params = {"folder_path": folder_path}
543+
return requests.delete(
544+
self._url(f"assignments/{assignment_id}/starter_file_groups/{starter_file_group_id}/remove_folder"),
545+
params=params,
546+
headers=self._auth_header,
547+
)
548+
549+
@parse_response("content")
550+
def download_starter_file_entries(self, assignment_id: int, starter_file_group_id: int) -> requests.Response:
551+
"""
552+
Return the content of a zipfile containing the content of all starter files from the starter file group with
553+
id=<starter_file_group_id>.
554+
"""
555+
return requests.get(
556+
self._url(f"assignments/{assignment_id}/starter_file_groups/{starter_file_group_id}/download_entries"),
557+
headers=self._auth_header,
558+
)
559+
560+
@parse_response("json")
561+
def get_starter_file_groups(self, assignment_id: int) -> requests.Response:
562+
"""
563+
Return all starter file groups for the assignment with id=<assignment_id>
564+
"""
565+
return requests.get(self._url(f"assignments/{assignment_id}/starter_file_groups"), headers=self._auth_header)
566+
567+
@parse_response("json")
568+
def create_starter_file_group(self, assignment_id: int) -> requests.Response:
569+
"""
570+
Create a starter file groups for the assignment with id=<assignment_id>
571+
"""
572+
return requests.post(self._url(f"assignments/{assignment_id}/starter_file_groups"), headers=self._auth_header)
573+
574+
@parse_response("json")
575+
def get_starter_file_group(self, assignment_id: int, starter_file_group_id: int) -> requests.Response:
576+
"""
577+
Return the starter file group with id=<starter_file_group_id> for the assignment with id=<assignment_id>
578+
"""
579+
return requests.get(
580+
self._url(f"assignments/{assignment_id}/starter_file_groups/{starter_file_group_id}"),
581+
headers=self._auth_header,
582+
)
583+
584+
@parse_response("json")
585+
def update_starter_file_group(
586+
self,
587+
assignment_id: int,
588+
starter_file_group_id: int,
589+
name: Optional[str] = None,
590+
entry_rename: Optional[str] = None,
591+
use_rename: Optional[bool] = None,
592+
) -> requests.Response:
593+
"""
594+
Update the starter file group with id=<starter_file_group_id> for the assignment with id=<assignment_id>
595+
"""
596+
params = {}
597+
if name is not None:
598+
params["name"] = name
599+
if entry_rename is not None:
600+
params["entry_rename"] = entry_rename
601+
if use_rename is not None:
602+
params["use_rename"] = use_rename
603+
return requests.put(
604+
self._url(f"assignments/{assignment_id}/starter_file_groups/{starter_file_group_id}"),
605+
params=params,
606+
headers=self._auth_header,
607+
)
608+
609+
@parse_response("json")
610+
def delete_starter_file_group(self, assignment_id: int, starter_file_group_id: int) -> requests.Response:
611+
"""
612+
Delete the starter file group with id=<starter_file_group_id> for the assignment with id=<assignment_id>
613+
"""
614+
return requests.delete(
615+
self._url(f"assignments/{assignment_id}/starter_file_groups/{starter_file_group_id}"),
616+
headers=self._auth_header,
617+
)

markusapi/tests/test_markusapi.py

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,3 +679,160 @@ class TestGetTestFiles(AbstractTestClass):
679679
@pytest.fixture
680680
def basic_call(api):
681681
yield api.get_test_files(1)
682+
683+
684+
class TestGetStarterFileEntries(AbstractTestClass):
685+
request_verb = "get"
686+
response_format = "json"
687+
url = "assignments/1/starter_file_groups/1/entries"
688+
689+
@staticmethod
690+
@pytest.fixture
691+
def basic_call(api):
692+
yield api.get_starter_file_entries(1, 1)
693+
694+
695+
class TestCreateStarterFile(AbstractTestClass):
696+
request_verb = "post"
697+
response_format = "json"
698+
url = "assignments/1/starter_file_groups/1/create_file"
699+
700+
@staticmethod
701+
@pytest.fixture
702+
def basic_call(api):
703+
yield api.create_starter_file(1, 1, "test.txt", "content")
704+
705+
def test_called_with_filename_and_content(self, api, response_mock):
706+
api.create_starter_file(1, 1, file_path="test.txt", contents="content")
707+
_, kwargs = response_mock.call_args
708+
assert kwargs["params"] == {"filename": "test.txt"}
709+
assert kwargs["files"] == {"file_content": ("test.txt", "content")}
710+
711+
712+
class TestCreateStarterFolder(AbstractTestClass):
713+
request_verb = "post"
714+
response_format = "json"
715+
url = "assignments/1/starter_file_groups/1/create_folder"
716+
717+
@staticmethod
718+
@pytest.fixture
719+
def basic_call(api):
720+
yield api.create_starter_folder(1, 1, "subdir")
721+
722+
def test_called_with_filename_and_content(self, api, response_mock):
723+
api.create_starter_folder(1, 1, folder_path="subdir")
724+
_, kwargs = response_mock.call_args
725+
assert kwargs["params"] == {"folder_path": "subdir"}
726+
727+
728+
class TestRemoveStarterFile(AbstractTestClass):
729+
request_verb = "delete"
730+
response_format = "json"
731+
url = "assignments/1/starter_file_groups/1/remove_file"
732+
733+
@staticmethod
734+
@pytest.fixture
735+
def basic_call(api):
736+
yield api.remove_starter_file(1, 1, "test.txt")
737+
738+
def test_called_with_filename(self, api, response_mock):
739+
api.remove_starter_file(1, 1, file_path="test.txt")
740+
_, kwargs = response_mock.call_args
741+
assert kwargs["params"] == {"filename": "test.txt"}
742+
743+
744+
class TestRemoveStarterFolder(AbstractTestClass):
745+
request_verb = "delete"
746+
response_format = "json"
747+
url = "assignments/1/starter_file_groups/1/remove_folder"
748+
749+
@staticmethod
750+
@pytest.fixture
751+
def basic_call(api):
752+
yield api.remove_starter_folder(1, 1, "subdir")
753+
754+
def test_called_with_filename_and_content(self, api, response_mock):
755+
api.remove_starter_folder(1, 1, folder_path="subdir")
756+
_, kwargs = response_mock.call_args
757+
assert kwargs["params"] == {"folder_path": "subdir"}
758+
759+
760+
class TestDownloadStarterFileEntries(AbstractTestClass):
761+
request_verb = "get"
762+
response_format = "content"
763+
url = "assignments/1/starter_file_groups/1/download_entries"
764+
765+
@staticmethod
766+
@pytest.fixture
767+
def basic_call(api):
768+
yield api.download_starter_file_entries(1, 1)
769+
770+
771+
class TestDownloadStarterFileGroups(AbstractTestClass):
772+
request_verb = "get"
773+
response_format = "json"
774+
url = "assignments/1/starter_file_groups"
775+
776+
@staticmethod
777+
@pytest.fixture
778+
def basic_call(api):
779+
yield api.get_starter_file_groups(1)
780+
781+
782+
class TestCreateStarterFileGroup(AbstractTestClass):
783+
request_verb = "post"
784+
response_format = "json"
785+
url = "assignments/1/starter_file_groups"
786+
787+
@staticmethod
788+
@pytest.fixture
789+
def basic_call(api):
790+
yield api.create_starter_file_group(1)
791+
792+
793+
class TestGetStarterFileGroup(AbstractTestClass):
794+
request_verb = "get"
795+
response_format = "json"
796+
url = "assignments/1/starter_file_groups/1"
797+
798+
@staticmethod
799+
@pytest.fixture
800+
def basic_call(api):
801+
yield api.get_starter_file_group(1, 1)
802+
803+
804+
class TestUpdateStarterFileGroup(AbstractTestClass):
805+
request_verb = "put"
806+
response_format = "json"
807+
url = "assignments/1/starter_file_groups/1"
808+
809+
@staticmethod
810+
@pytest.fixture
811+
def basic_call(api):
812+
yield api.update_starter_file_group(1, 1)
813+
814+
def test_called_with_name(self, api, response_mock):
815+
api.update_starter_file_group(1, 1, name="some_name")
816+
_, kwargs = response_mock.call_args
817+
assert kwargs["params"] == {"name": "some_name"}
818+
819+
def test_called_with_entry_name(self, api, response_mock):
820+
api.update_starter_file_group(1, 1, entry_rename="some_entry_name")
821+
_, kwargs = response_mock.call_args
822+
assert kwargs["params"] == {"entry_rename": "some_entry_name"}
823+
824+
def test_called_with_use_rename(self, api, response_mock):
825+
api.update_starter_file_group(1, 1, use_rename=True)
826+
_, kwargs = response_mock.call_args
827+
assert kwargs["params"] == {"use_rename": True}
828+
829+
830+
class TestDeleteStarterFileGroup(AbstractTestClass):
831+
request_verb = "delete"
832+
response_format = "json"
833+
url = "assignments/1/starter_file_groups/1"
834+
835+
@staticmethod
836+
@pytest.fixture
837+
def basic_call(api):
838+
yield api.delete_starter_file_group(1, 1)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setuptools.setup(
77
name="markusapi",
8-
version="0.2.0",
8+
version="0.2.1",
99
author="Alessio Di Sandro, Misha Schwartz",
1010
author_email="[email protected]",
1111
description="Interface to interact with MarkUs API",

0 commit comments

Comments
 (0)