From 8b2e897d46c5a3f282c2443db2737f2ff4c56848 Mon Sep 17 00:00:00 2001 From: Boris Lau Date: Sat, 6 Jan 2024 17:24:45 -0800 Subject: [PATCH 1/6] Added import_pgn api support --- README.rst | 1 + berserk/clients/studies.py | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 1d4f910..df2f8ae 100644 --- a/README.rst +++ b/README.rst @@ -170,6 +170,7 @@ Most of the API is available: client.studies.export_chapter client.studies.export client.studies.export_by_username + client.studies.import_pgn client.tablebase.look_up client.tablebase.standard diff --git a/berserk/clients/studies.py b/berserk/clients/studies.py index 05223dc..0dba237 100644 --- a/berserk/clients/studies.py +++ b/berserk/clients/studies.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Iterator +from typing import Dict, Iterator from ..formats import PGN from .base import BaseClient @@ -35,3 +35,25 @@ def export_by_username(self, username: str) -> Iterator[str]: return:iterator over all chapters as PGN""" path = f"/study/by/{username}/export.pgn" yield from self._r.get(path, fmt=PGN, stream=True) + + def import_pgn( + self, study_id: str, chapter_name: str, pgn: str, + orientation: str = "white", variant: str = "standard" + ) -> Iterator[Dict[str, str]]: + """Imports arbitrary PGN into an existing study. + Creates a new chapter in the study. + + return: Iterator over the chapter {id, name}""" + # https://lichess.org/api/study/{studyId}/import-pgn + path = f"/api/study/{study_id}/import-pgn" + payload = { + "name": chapter_name, + "pgn": pgn, + "orientation": orientation, + "variant": variant, + } + # The return is of the form: + # {chapters:[{id: "chapterId", name: "chapterName"}]} + yield from ( + c for c in self._r.post(path, data=payload).get("chapters", []) + ) From 4bba757832130d0949a3cafd5f8049980caab9cb Mon Sep 17 00:00:00 2001 From: Boris Lau Date: Sat, 6 Jan 2024 17:26:31 -0800 Subject: [PATCH 2/6] lint --- berserk/clients/studies.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/berserk/clients/studies.py b/berserk/clients/studies.py index 0dba237..fed6de7 100644 --- a/berserk/clients/studies.py +++ b/berserk/clients/studies.py @@ -37,8 +37,12 @@ def export_by_username(self, username: str) -> Iterator[str]: yield from self._r.get(path, fmt=PGN, stream=True) def import_pgn( - self, study_id: str, chapter_name: str, pgn: str, - orientation: str = "white", variant: str = "standard" + self, + study_id: str, + chapter_name: str, + pgn: str, + orientation: str = "white", + variant: str = "standard", ) -> Iterator[Dict[str, str]]: """Imports arbitrary PGN into an existing study. Creates a new chapter in the study. @@ -54,6 +58,4 @@ def import_pgn( } # The return is of the form: # {chapters:[{id: "chapterId", name: "chapterName"}]} - yield from ( - c for c in self._r.post(path, data=payload).get("chapters", []) - ) + yield from (c for c in self._r.post(path, data=payload).get("chapters", [])) From 603cc980b90f928caea20f1cefa5e56845fc2d57 Mon Sep 17 00:00:00 2001 From: Boris Lau Date: Sat, 6 Jan 2024 17:35:17 -0800 Subject: [PATCH 3/6] Added To be released to CHANGELOG --- CHANGELOG.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9f60ee7..f96401d 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,11 @@ Changelog ========= +To be released +-------------- + +* Added ``studies.import_pgn`` to import PGN to study + v0.13.2 (2023-12-04) -------------------- From 885ce3680cc59b6d7cead548a8fb3169b664e505 Mon Sep 17 00:00:00 2001 From: kraktus Date: Sun, 7 Jan 2024 17:14:20 +0100 Subject: [PATCH 4/6] study import-pgn: enhance doc and typing Document the PGN can contain multiple games and for each game one chapter is created. Type function arguments, and do not return a generator but a list because the endpoint is not streaming. Use TypedDict because we know the keys and values. --- berserk/__init__.py | 2 ++ berserk/clients/studies.py | 17 +++++++++++------ berserk/types/__init__.py | 2 ++ berserk/types/studies.py | 8 ++++++++ 4 files changed, 23 insertions(+), 6 deletions(-) create mode 100644 berserk/types/studies.py diff --git a/berserk/__init__.py b/berserk/__init__.py index 14dc0b5..9c5eb42 100644 --- a/berserk/__init__.py +++ b/berserk/__init__.py @@ -16,6 +16,7 @@ BroadcastPlayer, Team, LightUser, + ChapterIdName, OnlineLightUser, OpeningStatistic, PaginatedTeams, @@ -35,6 +36,7 @@ __all__ = [ "ArenaResult", "BroadcastPlayer", + "ChapterIdName", "Client", "JSON", "JSON_LIST", diff --git a/berserk/clients/studies.py b/berserk/clients/studies.py index fed6de7..c2584a9 100644 --- a/berserk/clients/studies.py +++ b/berserk/clients/studies.py @@ -1,8 +1,10 @@ from __future__ import annotations -from typing import Dict, Iterator +from typing import Iterator from ..formats import PGN +from ..types.common import Color, Variant +from ..types import ChapterIdName from .base import BaseClient @@ -41,12 +43,16 @@ def import_pgn( study_id: str, chapter_name: str, pgn: str, - orientation: str = "white", - variant: str = "standard", - ) -> Iterator[Dict[str, str]]: + orientation: Color = "white", + variant: Variant = "standard", + ) -> list[ChapterIdName]: """Imports 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. + + Note that a study can contain at most 64 chapters. + return: Iterator over the chapter {id, name}""" # https://lichess.org/api/study/{studyId}/import-pgn path = f"/api/study/{study_id}/import-pgn" @@ -57,5 +63,4 @@ def import_pgn( "variant": variant, } # The return is of the form: - # {chapters:[{id: "chapterId", name: "chapterName"}]} - yield from (c for c in self._r.post(path, data=payload).get("chapters", [])) + return self._r.post(path, data=payload).get("chapters", []) diff --git a/berserk/types/__init__.py b/berserk/types/__init__.py index a665f88..5962bb9 100644 --- a/berserk/types/__init__.py +++ b/berserk/types/__init__.py @@ -11,6 +11,7 @@ OpeningStatistic, Speed, ) +from .studies import ChapterIdName from .team import PaginatedTeams, Team from .tournaments import ArenaResult, CurrentTournaments, SwissResult, SwissInfo @@ -21,6 +22,7 @@ "BulkPairing", "BulkPairingGame", "Challenge", + "ChapterIdName", "ClockConfig", "CurrentTournaments", "ExternalEngine", diff --git a/berserk/types/studies.py b/berserk/types/studies.py new file mode 100644 index 0000000..0fefedc --- /dev/null +++ b/berserk/types/studies.py @@ -0,0 +1,8 @@ +from __future__ import annotations + +from typing_extensions import TypedDict + + +class ChapterIdName(TypedDict): + id: str + name: str From 630ef8731dcb3ad2aa7499c660340aa2541a59c9 Mon Sep 17 00:00:00 2001 From: kraktus Date: Sun, 7 Jan 2024 17:24:32 +0100 Subject: [PATCH 5/6] cast the returned value and fix doc return type --- berserk/clients/studies.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/berserk/clients/studies.py b/berserk/clients/studies.py index c2584a9..e6f3c3e 100644 --- a/berserk/clients/studies.py +++ b/berserk/clients/studies.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Iterator +from typing import cast, Iterator from ..formats import PGN from ..types.common import Color, Variant @@ -53,7 +53,7 @@ def import_pgn( Note that a study can contain at most 64 chapters. - return: Iterator over the chapter {id, name}""" + return: List of the chapters {id, name}""" # https://lichess.org/api/study/{studyId}/import-pgn path = f"/api/study/{study_id}/import-pgn" payload = { @@ -63,4 +63,6 @@ def import_pgn( "variant": variant, } # The return is of the form: - return self._r.post(path, data=payload).get("chapters", []) + return cast( + list[ChapterIdName], self._r.post(path, data=payload).get("chapters", []) + ) From 8f9720aeb8ca3f93544b06cb9ee446b982d3a8e0 Mon Sep 17 00:00:00 2001 From: kraktus Date: Sun, 7 Jan 2024 17:26:37 +0100 Subject: [PATCH 6/6] py 3.8 type fix --- berserk/clients/studies.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/berserk/clients/studies.py b/berserk/clients/studies.py index e6f3c3e..c9bac0e 100644 --- a/berserk/clients/studies.py +++ b/berserk/clients/studies.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import cast, Iterator +from typing import cast, List, Iterator from ..formats import PGN from ..types.common import Color, Variant @@ -45,7 +45,7 @@ def import_pgn( pgn: str, orientation: Color = "white", variant: Variant = "standard", - ) -> list[ChapterIdName]: + ) -> List[ChapterIdName]: """Imports arbitrary PGN into an existing study. Creates a new chapter in the study. @@ -64,5 +64,5 @@ def import_pgn( } # The return is of the form: return cast( - list[ChapterIdName], self._r.post(path, data=payload).get("chapters", []) + List[ChapterIdName], self._r.post(path, data=payload).get("chapters", []) )