Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
94 commits
Select commit Hold shift + click to select a range
6b85ebd
Implement broadcasts.get_top: types, validation,
DoraFgr Oct 22, 2025
982db3e
Refactor test_get_top_valid to include skip_if_older_3_dot_10 decorator
DoraFgr Oct 22, 2025
7725f41
Remove runtime guards and isinstance test for broadcast get_top method
DoraFgr Oct 22, 2025
f523fa5
Refactor test for getting top broadcasts
DoraFgr Oct 23, 2025
2d5d0b1
Refactor TypedDict classes for broadcasts: unify naming and add Custo…
DoraFgr Oct 23, 2025
b4936f4
Rename BroadcastTopResponse to BroadcastTop to align with API Docs.
DoraFgr Oct 23, 2025
9a2efcc
Added endpoint and Pydantic validation
JAMoreno-Larios Oct 25, 2025
fb1a698
Added unit test and cassette
JAMoreno-Larios Oct 25, 2025
ffdd040
Added test for integration testing with Docker image
JAMoreno-Larios Oct 25, 2025
9c0bea8
Updated and
JAMoreno-Larios Oct 25, 2025
dd67b33
Fixed an issue with docstring.
JAMoreno-Larios Oct 25, 2025
3a196e4
Replaced with . Extended to handle the field.
JAMoreno-Larios Oct 26, 2025
1c06f38
Fixed an error in extension made in prior commit.
JAMoreno-Larios Oct 27, 2025
803ba19
Updated cassette for timeline test.
JAMoreno-Larios Oct 27, 2025
7c6b70d
make sure the `upcoming` field pseudo-deprecated for typechekers
kraktus Nov 12, 2025
4db8d0e
remove `upcoming` from `get_top` description as always empty
kraktus Nov 12, 2025
f6613cb
Merge pull request #128 from DoraFgr/feature/BroadcastGetTopEndpoint
kraktus Nov 12, 2025
0c18ef0
make changelog easier for git not to create unnecessary conflicts
kraktus Nov 12, 2025
a21a07d
add block and unblock endpoints, testing for relations
MrElyazid Nov 9, 2025
0754b8c
update changelog.rst
kraktus Nov 12, 2025
71cac12
Move test to block/unblock to integration tests, as we only want to c…
kraktus Nov 12, 2025
7575931
Merge pull request #131 from MrElyazid/master
kraktus Nov 12, 2025
8c12375
Deprecate Python 3.9 support
gameroman Nov 14, 2025
d7ecfc7
fix + update changelog
gameroman Nov 14, 2025
a91a534
Use `ruff` for formatting instead of black and docformatter
kraktus Nov 17, 2025
0b53094
slightly more complete changelog
kraktus Nov 17, 2025
354723d
Initial plan
Copilot Nov 17, 2025
36836ef
Merge pull request #133 from GameRoMan/chore/deprecate-python-3-9
kraktus Nov 17, 2025
dc69d55
Add Dependabot configuration for Python runtime dependencies
Copilot Nov 17, 2025
fe995bd
do not explicitely ignore deps
kraktus Nov 17, 2025
03584af
Merge pull request #135 from lichess-org/copilot/update-dependencies-…
kraktus Nov 17, 2025
a7ac43d
Initial plan
Copilot Nov 17, 2025
fcc917a
Initial plan
Copilot Nov 17, 2025
a9de2a5
Initial plan
Copilot Nov 17, 2025
2a65f43
use a proper dockerfile for faster integration tests
kraktus Nov 17, 2025
1273b3e
tweak integration test to use built image
kraktus Nov 17, 2025
6807db8
remove unneeded make setup from integration tests script
kraktus Nov 17, 2025
25f8139
commit skeleton for local.py
kraktus Nov 18, 2025
7393331
style: Apply minor formatting and style fixes
kraktus Nov 18, 2025
9b3afb5
refactor: Port local integration tests from shell to Python
kraktus Nov 18, 2025
ee820e9
refactor: introduce `run` helper for consistent subprocess execution
kraktus Nov 18, 2025
0988ac5
WIP move to python for local integration tests
kraktus Nov 18, 2025
82e960e
remove old integration script
kraktus Nov 18, 2025
05f32e4
wip
kraktus Nov 18, 2025
49ac894
chore: Remove unused HTTP retry constants and imports
kraktus Nov 18, 2025
7f0af10
feat: Add watch mode for integration tests with file monitoring
kraktus Nov 18, 2025
2708fb6
build: Add requests, urllib3, watchdog to script dependencies
kraktus Nov 18, 2025
7f34712
Add watch-mode to integration tests
kraktus Nov 18, 2025
4b92d00
fix typing for local.py
kraktus Nov 18, 2025
b0ec51a
Allow to specify python version in integration Dockerfile
kraktus Nov 18, 2025
e3f492a
try to use same setup for CI integration tests as local
kraktus Nov 18, 2025
123b1c3
default to None if .python-version is missing,
kraktus Nov 18, 2025
922fef0
Merge pull request #136 from lichess-org/faster_integration
kraktus Nov 18, 2025
68b0b99
bend over and add more AI instruction files
kraktus Nov 18, 2025
7546a09
Fix typo in release.py
kraktus Nov 18, 2025
0af2003
use build-ing uv_build backend
kraktus Nov 18, 2025
24c1081
Implement release.yml to use trusted-publishing for pushing to Pypi (…
kraktus Nov 18, 2025
718a5e6
Update release.py
kraktus Nov 18, 2025
d13bdf7
Update .github/workflows/release.yml
kraktus Nov 18, 2025
0f8519e
Merge pull request #137 from lichess-org/pypi_trusted_publishing
kraktus Nov 18, 2025
5b911d4
checkout v5
kraktus Nov 18, 2025
2b6383e
stop with emoji nonsense
kraktus Nov 18, 2025
dfff029
ci: Allow configurable PyPI target environment for release workflow
kraktus Nov 18, 2025
b2b5807
Configure git in action
kraktus Nov 19, 2025
9a83a2f
add write permission to build CI, to push commits and tags
kraktus Nov 19, 2025
c94d989
include changelog in commit
kraktus Nov 19, 2025
82e46c8
add write permission to build CI, to push commits and tags
kraktus Nov 19, 2025
2ffc390
fix tag pushing
kraktus Nov 19, 2025
9a2c010
foo
kraktus Nov 19, 2025
380d1c6
fix pre-hook
kraktus Nov 19, 2025
7facb86
fix release commit
kraktus Nov 19, 2025
2f01b27
fix changelog
kraktus Nov 19, 2025
5a48510
env branch name
kraktus Nov 19, 2025
7625a56
debug
kraktus Nov 19, 2025
976806c
Merge pull request #138 from lichess-org/testpypi
kraktus Nov 19, 2025
dba2942
uses subprocess to try to fix multi-line issue in github action
kraktus Nov 19, 2025
fa24e10
use credentials to push
kraktus Nov 19, 2025
93d920f
Added `/api/games/export/import` endpoint with `Client.games.export_i…
JAMoreno-Larios Oct 26, 2025
5d246b1
Added test for `Client.games.export_imported_games()`
JAMoreno-Larios Oct 26, 2025
1870e37
Updated and
JAMoreno-Larios Oct 26, 2025
e86fd2a
Ensured that the endpoint name does not repeat the name of the client.
JAMoreno-Larios Oct 26, 2025
b04f2a1
Added endpoint test to integration test suite.
JAMoreno-Larios Oct 27, 2025
eb9174c
fix integration tests after moving test file
kraktus Nov 19, 2025
c507895
remove tests/clients/test_games.py as it's not reproducible
kraktus Nov 19, 2025
82a9fdc
Merge pull request #130 from JAMoreno-Larios/jaml_export_imports
kraktus Nov 19, 2025
81ec32b
Added endpoint and Pydantic validation
JAMoreno-Larios Oct 25, 2025
427d53a
Added unit test and cassette
JAMoreno-Larios Oct 25, 2025
a95c313
Added test for integration testing with Docker image
JAMoreno-Larios Oct 25, 2025
214abde
Fixed CHANGELOG.rst conflict between branches
JAMoreno-Larios Oct 25, 2025
b0bd095
Fixed an issue with docstring.
JAMoreno-Larios Oct 25, 2025
5ec74b9
Replaced with . Extended to handle the field.
JAMoreno-Larios Oct 26, 2025
55b6a24
Fixed an error in extension made in prior commit.
JAMoreno-Larios Oct 27, 2025
2992f07
Updated cassette for timeline test.
JAMoreno-Larios Oct 27, 2025
e426f0d
Fixed some merging issues
JAMoreno-Larios Nov 20, 2025
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
15 changes: 14 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Set update schedule for GitHub Actions
# Set update schedule for GitHub Actions and Python dependencies

version: 2
updates:
Expand All @@ -8,3 +8,16 @@ updates:
schedule:
# Check for updates to GitHub Actions every week
interval: "weekly"

- package-ecosystem: "pip"
directory: "/"
schedule:
# Check for updates to Python dependencies every week
interval: "weekly"
# Only check runtime dependencies, not dev dependencies
# Dependabot only checks the main dependencies array in pyproject.toml
# and ignores dependency-groups by default
groups:
dependencies:
patterns:
- "*"
19 changes: 4 additions & 15 deletions .github/workflows/integration_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,14 @@ on:

jobs:
lila:
runs-on: ubuntu-24.04
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
container: ubuntu:latest
services:
bdit_lila:
image: ghcr.io/lichess-org/lila-docker:main
options: --restart=always
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
steps:
- uses: actions/checkout@v5
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
python-version: ${{ matrix.python-version }}
- name: Install make and curl
run: apt update && apt install -y make curl
- name: Install dependencies
run: make setup
uses: astral-sh/setup-uv@v7 # latest
- name: Run integration tests
run: |
./integration/run-tests.sh
./integration/local.py --python ${{ matrix.python-version }}
74 changes: 74 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: Publish to Pypi (and testPypi)

on:
workflow_dispatch:
inputs:
bump:
description: 'bump version: major, minor, patch, or none to build current dev'
required: true
type: choice
options:
- none
- major
- minor
- patch
environment:
description: 'Target environment: testpypi or pypi'
required: true
type: choice
options:
- testpypi
- pypi
default: 'testpypi'

jobs:
build:
name: Build package
runs-on: ubuntu-latest

permissions:
contents: write

env:
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}

steps:
- uses: actions/checkout@v5
- name: Configure Git
run: |
git config user.name github-actions
git config user.email github-actions@github.com
- name: Install uv
uses: astral-sh/setup-uv@v7
- name: Build berserk package
run: uv run release.py --bump ${{ github.event.inputs.bump }} --branch ${{ env.BRANCH_NAME }}
- name: Store the distribution packages
uses: actions/upload-artifact@v4
with:
name: python-package-distributions
path: dist/

publish:
name: Publish to ${{ github.event.inputs.environment }}
needs:
- build
runs-on: ubuntu-latest
if: github.event.inputs.environment == 'testpypi' || github.event.inputs.environment == 'pypi'

environment:
name: ${{ github.event.inputs.environment }}
url: ${{ github.event.inputs.environment == 'testpypi' && 'https://test.pypi.org/p/berserk' || 'https://pypi.org/p/berserk' }}

permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing

steps:
- name: Download all the dists
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/
- name: Publish to ${{ github.event.inputs.environment }}
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: ${{ github.event.inputs.environment == 'testpypi' && 'https://test.pypi.org/legacy/' || 'https://upload.pypi.org/legacy/' }}
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/typing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
Expand Down
16 changes: 15 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,23 @@ Changelog
To be released
--------------


* Deprecate Python 3.9 support - minimum required version is now Python 3.10+. This does not mean the library will not work with Python 3.9, but it will not be tested against it anymore.

* Added ``pgn_in_json`` parameter to ``client.games.export``.
* Implement `broadcasts.get_top()` endpoint; typing fixes and validation.
* Added ``client.relations.block`` and ``client.relations.unblock`` for blocking/unblocking users.
* Implemented ``/api/games/export/imports`` under
``client.games.export_imported``.
* Added ``client.account.get_timeline`` to get current logged user timeline.

Thanks to all the contributors who helped to this release:
- @hsheth2
- @DoraFgr
- @MrElyazid
- @gameroman
- @JAMoreno-Larios

Thanks to @hsheth2 for their contributions to this release.

v0.14.0 (2025-08-26)
--------------------
Expand Down
3 changes: 3 additions & 0 deletions CONVENTIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- use types everywhere
- NEVER use `try` and `except` blocks
- use as few logging as possible
16 changes: 9 additions & 7 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ clean-test: ## remove test and coverage artifacts
rm -fr .pytest_cache

setup: ## setup uv env and install dependencies
uv sync
uv sync --locked

setup-ci: ## for Docker, install the deps only. need to run `setup` after
uv sync --locked --no-install-project

test: ## run tests with pytest
uv run pytest tests
Expand All @@ -33,14 +36,13 @@ test_record: ## run tests with pytest and record http requests
uv run pytest --record-mode=once

typecheck: ## run type checking with pyright
uv run pyright berserk
uv run pyright berserk integration/local.py

format: ## format python files with black and docformatter
uv run black berserk tests check-endpoints.py release.py
uv run docformatter --in-place --black berserk/*.py
format: ## format python files with ruff
uv run ruff format

format-check: ## check formatting with black (for CI)
uv run black berserk tests check-endpoints.py release.py --check
format-check: ## check formatting with ruff (for CI)
uv run ruff format . --diff

docs: ## generate Sphinx HTML documentation, including API docs
uv run sphinx-build -b html docs _build -EW --keep-going
Expand Down
7 changes: 6 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ This is based on the `original berserk version created by rhgrant10 <https://git
Installation
------------

Requires Python 3.9+. Download and install the latest release:
Requires Python 3.10+. Download and install the latest release:
::

pip3 install berserk
Expand Down Expand Up @@ -70,6 +70,7 @@ Most of the API is available:
client.account.get_kid_mode
client.account.set_kid_mode
client.account.upgrade_to_bot
client.account.get_timeline

client.analysis.get_cloud_evaluation

Expand Down Expand Up @@ -113,6 +114,7 @@ Most of the API is available:
client.broadcasts.get_round_pgns
client.broadcasts.get_pgns
client.broadcasts.stream_round
client.broadcasts.get_top

client.bulk_pairings.get_upcoming
client.bulk_pairings.create
Expand Down Expand Up @@ -150,6 +152,7 @@ Most of the API is available:
client.games.export_ongoing_by_player
client.games.export_by_player
client.games.export_multi
client.games.export_imported
client.games.get_among_players
client.games.stream_games_by_ids
client.games.add_game_ids_to_stream
Expand All @@ -173,6 +176,8 @@ Most of the API is available:
client.relations.get_users_followed
client.relations.follow
client.relations.unfollow
client.relations.block
client.relations.unblock

client.simuls.get

Expand Down
1 change: 1 addition & 0 deletions berserk/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# ruff: noqa: E402
"""Top-level package for berserk."""

from importlib import metadata
Expand Down
14 changes: 13 additions & 1 deletion berserk/clients/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import cast

from .. import models
from ..types.account import AccountInformation, Preferences
from ..types.account import AccountInformation, Preferences, Timeline
from .base import BaseClient


Expand Down Expand Up @@ -60,3 +60,15 @@ def upgrade_to_bot(self):
"""
path = "/api/bot/account/upgrade"
self._r.post(path)

def get_timeline(self, since: int = 1356998400070, nb: int = 15) -> Timeline:
"""
Get the timeline events of the logged in user.
Requires OAuth2 authorization.

:param since: shows events since the provided timestamp, default
1356998400070 (the earliest allowed by Lichess
:param nb: Max number of events to fetch, default 15.
"""
path = "/api/timeline"
return cast(Timeline, self._r.get(path))
19 changes: 17 additions & 2 deletions berserk/clients/broadcasts.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from __future__ import annotations

from typing import Iterator, Any, Dict, List
from typing import Iterator, Any, Dict, List, cast

from .. import models
from ..formats import PGN
from .base import BaseClient

from ..types.broadcast import BroadcastPlayer
from ..types.broadcast import BroadcastPlayer, BroadcastTop
from ..utils import to_str


Expand Down Expand Up @@ -244,3 +244,18 @@ def stream_my_rounds(self, nb: int | None = None) -> Iterator[Dict[str, Any]]:
path = "/api/broadcast/my-rounds"
params = {"nb": nb}
yield from self._r.get(path, params=params, stream=True)

def get_top(
self,
page: int = 1,
html: bool = False,
) -> BroadcastTop:
"""Return the paginated top broadcasts structure for `page`.

:param page: which page to fetch (1..20). Only page 1 has `active` broadcasts.
:param html: if True, convert the `description` field from markdown to HTML.
:return: parsed JSON response with keys `active` and `past`.
"""
path = "/api/broadcast/top"
params = {"page": page, "html": html}
return cast(BroadcastTop, self._r.get(path, params=params))
11 changes: 11 additions & 0 deletions berserk/clients/games.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,3 +317,14 @@ def import_game(self, pgn: str) -> Dict[str, Any]:
"pgn": pgn,
}
return self._r.post(path, data=payload)

def export_imported(self) -> str:
"""
Export all the imported games by the currently logged in user
as a PGN.
Requires OAuth2 authorization.

:return: the exported games in a single string
"""
path = "/api/games/export/imports"
return self._r.get(path, fmt=PGN, stream=False)
16 changes: 16 additions & 0 deletions berserk/clients/relations.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,19 @@ def unfollow(self, username: str):
"""
path = f"/api/rel/unfollow/{username}"
self._r.post(path)

def block(self, username: str):
"""Block a player.

:param username: user to block
"""
path = f"/api/rel/block/{username}"
self._r.post(path)

def unblock(self, username: str):
"""Unblock a player.

:param username: user to unblock
"""
path = f"/api/rel/unblock/{username}"
self._r.post(path)
14 changes: 13 additions & 1 deletion berserk/types/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

from datetime import datetime

from typing_extensions import TypedDict, TypeAlias, Literal
from typing_extensions import TypedDict, TypeAlias, Literal, NotRequired
from .common import LightUser


class Perf(TypedDict):
Expand Down Expand Up @@ -120,3 +121,14 @@ class UserPreferences(TypedDict, total=False):
class Preferences(TypedDict):
prefs: UserPreferences
language: str


class TimelineEntry(TypedDict):
type: NotRequired[str]
data: NotRequired[dict[str, str] | None]
date: int


class Timeline(TypedDict):
entries: list[TimelineEntry]
users: dict[str, LightUser]
Loading