From 5a242e1505951d9f05fbf0e39c06e7018c884176 Mon Sep 17 00:00:00 2001 From: johndoknjas Date: Mon, 21 Oct 2024 03:28:05 -0700 Subject: [PATCH 1/4] For studies, allow the user to specify values for default query params. --- berserk/clients/studies.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/berserk/clients/studies.py b/berserk/clients/studies.py index c9bac0e..1731622 100644 --- a/berserk/clients/studies.py +++ b/berserk/clients/studies.py @@ -7,27 +7,40 @@ from ..types import ChapterIdName from .base import BaseClient +def append_query_params(url: str, clocks: bool, comments: bool, variations: bool, + source: bool, orientation: bool) -> str: + pairs = {'clocks': clocks, 'comments': comments, 'variations': variations, + 'source': source, 'orientation': orientation} + return f'{url}?' + '&'.join(f'{k}={str(pairs[k]).lower()}' for k in pairs) class Studies(BaseClient): """Study chess the Lichess way.""" - def export_chapter(self, study_id: str, chapter_id: str) -> str: + def export_chapter(self, study_id: str, chapter_id: str, clocks: bool = True, + comments: bool = True, variations: bool = True, source: bool = False, + orientation: bool = False) -> str: """Export one chapter of a study. :return: chapter PGN """ - path = f"/api/study/{study_id}/{chapter_id}.pgn" + path = append_query_params(f"/api/study/{study_id}/{chapter_id}.pgn", + clocks, comments, variations, source, orientation) return self._r.get(path, fmt=PGN) - def export(self, study_id: str) -> Iterator[str]: + def export(self, study_id: str, clocks: bool = True, comments: bool = True, + variations: bool = True, source: bool = False, + orientation: bool = False) -> Iterator[str]: """Export all chapters of a study. :return: iterator over all chapters as PGN """ - path = f"/api/study/{study_id}.pgn" + path = append_query_params(f"/api/study/{study_id}.pgn", + clocks, comments, variations, source, orientation) yield from self._r.get(path, fmt=PGN, stream=True) - def export_by_username(self, username: str) -> Iterator[str]: + def export_by_username(self, username: str, clocks: bool = True, comments: bool = True, + variations: bool = True, source: bool = False, + orientation: bool = False) -> Iterator[str]: """Export all chapters of all studies of a user in PGN format. If authenticated, then all public, unlisted, and private studies are included. @@ -35,7 +48,8 @@ def export_by_username(self, username: str) -> Iterator[str]: If not, only public (non-unlisted) studies are included. return:iterator over all chapters as PGN""" - path = f"/study/by/{username}/export.pgn" + path = append_query_params(f"/study/by/{username}/export.pgn", + clocks, comments, variations, source, orientation) yield from self._r.get(path, fmt=PGN, stream=True) def import_pgn( From b62f8170fb73acd7c3c245cf1745199e553b6c99 Mon Sep 17 00:00:00 2001 From: johndoknjas Date: Mon, 21 Oct 2024 03:33:52 -0700 Subject: [PATCH 2/4] Format with black. --- berserk/clients/studies.py | 90 +++++++++++++++++++++++++++++--------- 1 file changed, 70 insertions(+), 20 deletions(-) diff --git a/berserk/clients/studies.py b/berserk/clients/studies.py index 1731622..b6f3bba 100644 --- a/berserk/clients/studies.py +++ b/berserk/clients/studies.py @@ -7,40 +7,84 @@ from ..types import ChapterIdName from .base import BaseClient -def append_query_params(url: str, clocks: bool, comments: bool, variations: bool, - source: bool, orientation: bool) -> str: - pairs = {'clocks': clocks, 'comments': comments, 'variations': variations, - 'source': source, 'orientation': orientation} - return f'{url}?' + '&'.join(f'{k}={str(pairs[k]).lower()}' for k in pairs) + +def append_query_params( + url: str, + clocks: bool, + comments: bool, + variations: bool, + source: bool, + orientation: bool, +) -> str: + pairs = { + "clocks": clocks, + "comments": comments, + "variations": variations, + "source": source, + "orientation": orientation, + } + return f"{url}?" + "&".join(f"{k}={str(pairs[k]).lower()}" for k in pairs) + class Studies(BaseClient): """Study chess the Lichess way.""" - def export_chapter(self, study_id: str, chapter_id: str, clocks: bool = True, - comments: bool = True, variations: bool = True, source: bool = False, - orientation: bool = False) -> str: + def export_chapter( + self, + study_id: str, + chapter_id: str, + clocks: bool = True, + comments: bool = True, + variations: bool = True, + source: bool = False, + orientation: bool = False, + ) -> str: """Export one chapter of a study. :return: chapter PGN """ - path = append_query_params(f"/api/study/{study_id}/{chapter_id}.pgn", - clocks, comments, variations, source, orientation) + path = append_query_params( + f"/api/study/{study_id}/{chapter_id}.pgn", + clocks, + comments, + variations, + source, + orientation, + ) return self._r.get(path, fmt=PGN) - def export(self, study_id: str, clocks: bool = True, comments: bool = True, - variations: bool = True, source: bool = False, - orientation: bool = False) -> Iterator[str]: + def export( + self, + study_id: str, + clocks: bool = True, + comments: bool = True, + variations: bool = True, + source: bool = False, + orientation: bool = False, + ) -> Iterator[str]: """Export all chapters of a study. :return: iterator over all chapters as PGN """ - path = append_query_params(f"/api/study/{study_id}.pgn", - clocks, comments, variations, source, orientation) + path = append_query_params( + f"/api/study/{study_id}.pgn", + clocks, + comments, + variations, + source, + orientation, + ) yield from self._r.get(path, fmt=PGN, stream=True) - def export_by_username(self, username: str, clocks: bool = True, comments: bool = True, - variations: bool = True, source: bool = False, - orientation: bool = False) -> Iterator[str]: + def export_by_username( + self, + username: str, + clocks: bool = True, + comments: bool = True, + variations: bool = True, + source: bool = False, + orientation: bool = False, + ) -> Iterator[str]: """Export all chapters of all studies of a user in PGN format. If authenticated, then all public, unlisted, and private studies are included. @@ -48,8 +92,14 @@ def export_by_username(self, username: str, clocks: bool = True, comments: bool If not, only public (non-unlisted) studies are included. return:iterator over all chapters as PGN""" - path = append_query_params(f"/study/by/{username}/export.pgn", - clocks, comments, variations, source, orientation) + path = append_query_params( + f"/study/by/{username}/export.pgn", + clocks, + comments, + variations, + source, + orientation, + ) yield from self._r.get(path, fmt=PGN, stream=True) def import_pgn( From 455195456778813bfa39f6c2a5fc4c22f86b772d Mon Sep 17 00:00:00 2001 From: johndoknjas Date: Mon, 28 Oct 2024 14:32:56 -0700 Subject: [PATCH 3/4] Apply PR feedback - do not manually add query param values to the path string. --- berserk/clients/studies.py | 72 ++++++++++++++------------------------ 1 file changed, 27 insertions(+), 45 deletions(-) diff --git a/berserk/clients/studies.py b/berserk/clients/studies.py index b6f3bba..305ecde 100644 --- a/berserk/clients/studies.py +++ b/berserk/clients/studies.py @@ -8,24 +8,6 @@ from .base import BaseClient -def append_query_params( - url: str, - clocks: bool, - comments: bool, - variations: bool, - source: bool, - orientation: bool, -) -> str: - pairs = { - "clocks": clocks, - "comments": comments, - "variations": variations, - "source": source, - "orientation": orientation, - } - return f"{url}?" + "&".join(f"{k}={str(pairs[k]).lower()}" for k in pairs) - - class Studies(BaseClient): """Study chess the Lichess way.""" @@ -43,15 +25,15 @@ def export_chapter( :return: chapter PGN """ - path = append_query_params( - f"/api/study/{study_id}/{chapter_id}.pgn", - clocks, - comments, - variations, - source, - orientation, - ) - return self._r.get(path, fmt=PGN) + path = f"/api/study/{study_id}/{chapter_id}.pgn" + params = { + "clocks": clocks, + "comments": comments, + "variations": variations, + "source": source, + "orientation": orientation, + } + return self._r.get(path, fmt=PGN, params=params) def export( self, @@ -66,15 +48,15 @@ def export( :return: iterator over all chapters as PGN """ - path = append_query_params( - f"/api/study/{study_id}.pgn", - clocks, - comments, - variations, - source, - orientation, - ) - yield from self._r.get(path, fmt=PGN, stream=True) + path = f"/api/study/{study_id}.pgn" + params = { + "clocks": clocks, + "comments": comments, + "variations": variations, + "source": source, + "orientation": orientation, + } + yield from self._r.get(path, fmt=PGN, stream=True, params=params) def export_by_username( self, @@ -92,15 +74,15 @@ def export_by_username( If not, only public (non-unlisted) studies are included. return:iterator over all chapters as PGN""" - path = append_query_params( - f"/study/by/{username}/export.pgn", - clocks, - comments, - variations, - source, - orientation, - ) - yield from self._r.get(path, fmt=PGN, stream=True) + path = f"/study/by/{username}/export.pgn" + params = { + "clocks": clocks, + "comments": comments, + "variations": variations, + "source": source, + "orientation": orientation, + } + yield from self._r.get(path, fmt=PGN, stream=True, params=params) def import_pgn( self, From 6bac736f21453786cc8dc28bea991f95f147096d Mon Sep 17 00:00:00 2001 From: johndoknjas Date: Mon, 28 Oct 2024 15:07:39 -0700 Subject: [PATCH 4/4] Update function docstrings to include info about params. --- berserk/clients/studies.py | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/berserk/clients/studies.py b/berserk/clients/studies.py index 305ecde..d92cec4 100644 --- a/berserk/clients/studies.py +++ b/berserk/clients/studies.py @@ -23,6 +23,13 @@ def export_chapter( ) -> str: """Export one chapter of a study. + :param study_id: study id + :param chapter_id: chapter id + :param clocks: include any clock comments in the PGN moves + :param comments: include any analysis and annotator comments in the PGN moves + :param variations: include any variations in the PGN moves + :param source: include a `Source` PGN tag containing the chapter URL + :param orientation: include an `Orientation` PGN tag containing the chapter's board orientation :return: chapter PGN """ path = f"/api/study/{study_id}/{chapter_id}.pgn" @@ -46,7 +53,13 @@ def export( ) -> Iterator[str]: """Export all chapters of a study. - :return: iterator over all chapters as PGN + :param study_id: study id + :param clocks: include any clock comments in the PGN moves + :param comments: include any analysis and annotator comments in the PGN moves + :param variations: include any variations in the PGN moves + :param source: for each chapter, include a `Source` PGN tag containing the chapter URL + :param orientation: for each chapter, include an `Orientation` PGN tag containing the chapter's board orientation + :return: iterator over all chapters as PGNs """ path = f"/api/study/{study_id}.pgn" params = { @@ -73,7 +86,14 @@ def export_by_username( If not, only public (non-unlisted) studies are included. - return:iterator over all chapters as PGN""" + :param username: the user whose studies will be exported + :param clocks: include any clock comments in the PGN moves + :param comments: include any analysis and annotator comments in the PGN moves + :param variations: include any variations in the PGN moves + :param source: for each chapter, include a `Source` PGN tag containing the chapter URL + :param orientation: for each chapter, include an `Orientation` PGN tag containing the chapter's board orientation + :return: iterator over all chapters as PGNs + """ path = f"/study/by/{username}/export.pgn" params = { "clocks": clocks, @@ -92,7 +112,7 @@ def import_pgn( orientation: Color = "white", variant: Variant = "standard", ) -> List[ChapterIdName]: - """Imports arbitrary PGN into an existing study. + """Imports an arbitrary PGN into an existing study. Creates a new chapter in the study. If the PGN contains multiple games (separated by 2 or more newlines) then multiple chapters will be created within the study.