vlrdevapi 2.4.0__tar.gz → 3.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/.github/workflows/docs-check.yml +13 -24
- vlrdevapi-3.0.0/.nvmrc +1 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/.readthedocs.yaml +3 -2
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/CHANGELOG.md +159 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/CODE_OF_CONDUCT.md +2 -1
- vlrdevapi-3.0.0/PKG-INFO +394 -0
- vlrdevapi-3.0.0/README.md +345 -0
- vlrdevapi-3.0.0/SECURITY.md +11 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/SUPPORT.md +2 -2
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/pyproject.toml +24 -12
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/scripts/check_mdx_examples.py +32 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/scripts/download_fixtures.py +131 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/__init__.py +1 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/__init__.pyi +13 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_base.py +65 -23
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_client.py +4 -4
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/info/namespace.pyi +6 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/info/parser.py +10 -9
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/list/namespace.pyi +6 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/list/parser.py +3 -2
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/matches/models.py +7 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/matches/namespace.py +1 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/matches/namespace.pyi +5 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/matches/parser.py +24 -7
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/namespace.pyi +5 -2
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/stages/namespace.pyi +6 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/stages/parser.py +3 -2
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/standings/namespace.pyi +6 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/standings/parser.py +6 -4
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/teams/namespace.pyi +6 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/teams/parser.py +2 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_matches/common.py +7 -45
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_matches/completed/namespace.pyi +6 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_matches/completed/parser.py +3 -2
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_matches/live/namespace.pyi +6 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_matches/live/parser.py +2 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_matches/namespace.pyi +6 -2
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_matches/upcoming/namespace.pyi +6 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_matches/upcoming/parser.py +3 -2
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_news/article/parser.py +5 -4
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_news/common.py +1 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_news/list/parser.py +2 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/__init__.py +1 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/_common_parsing.py +27 -9
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/agents/namespace.pyi +5 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/agents/parser.py +1 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/info/models.py +6 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/info/namespace.py +2 -2
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/info/namespace.pyi +6 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/info/parser.py +4 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/matches/namespace.pyi +7 -2
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/matches/parser.py +4 -14
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/namespace.py +46 -5
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/namespace.pyi +13 -2
- vlrdevapi-3.0.0/src/vlrdevapi/_player/placements/__init__.py +11 -0
- vlrdevapi-3.0.0/src/vlrdevapi/_player/placements/models.py +48 -0
- vlrdevapi-3.0.0/src/vlrdevapi/_player/placements/namespace.py +63 -0
- vlrdevapi-3.0.0/src/vlrdevapi/_player/placements/namespace.pyi +21 -0
- vlrdevapi-3.0.0/src/vlrdevapi/_player/placements/parser.py +147 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/profile/namespace.pyi +6 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/profile/parser.py +1 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/teams/namespace.pyi +6 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/teams/parser.py +1 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/__init__.py +3 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/_utils.py +1 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/economy/__init__.py +6 -0
- vlrdevapi-3.0.0/src/vlrdevapi/_series/economy/models.py +221 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/economy/namespace.py +26 -17
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/economy/namespace.pyi +4 -2
- vlrdevapi-3.0.0/src/vlrdevapi/_series/economy/parser.py +405 -0
- vlrdevapi-3.0.0/src/vlrdevapi/_series/info/__init__.py +17 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/info/models.py +42 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/info/namespace.pyi +6 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/info/parser.py +133 -13
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/match_namespace.py +42 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/match_namespace.pyi +16 -6
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/namespace.py +22 -2
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/namespace.pyi +10 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/performance/namespace.pyi +6 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/performance/parser.py +2 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/players/namespace.pyi +6 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/players/parser.py +54 -16
- vlrdevapi-3.0.0/src/vlrdevapi/_series/replay/__init__.py +25 -0
- vlrdevapi-3.0.0/src/vlrdevapi/_series/replay/models.py +344 -0
- vlrdevapi-3.0.0/src/vlrdevapi/_series/replay/namespace.py +214 -0
- vlrdevapi-3.0.0/src/vlrdevapi/_series/replay/namespace.pyi +18 -0
- vlrdevapi-3.0.0/src/vlrdevapi/_series/replay/parser.py +431 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/rounds/models.py +42 -11
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/rounds/namespace.py +85 -10
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/rounds/namespace.pyi +3 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/rounds/parser.py +19 -10
- vlrdevapi-3.0.0/src/vlrdevapi/_series/vods/__init__.py +8 -0
- vlrdevapi-3.0.0/src/vlrdevapi/_series/vods/models.py +63 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/vods/namespace.py +10 -10
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/vods/namespace.pyi +6 -1
- vlrdevapi-3.0.0/src/vlrdevapi/_series/vods/parser.py +135 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/completed_matches/models.py +12 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/completed_matches/namespace.py +46 -7
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/completed_matches/namespace.pyi +12 -3
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/completed_matches/parser.py +23 -9
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/info/namespace.py +3 -9
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/info/namespace.pyi +6 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/info/parser.py +1 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/namespace.py +16 -3
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/namespace.pyi +11 -5
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/placements/namespace.pyi +6 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/placements/parser.py +4 -3
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/roster/namespace.pyi +6 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/roster/parser.py +7 -5
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/stats/namespace.py +1 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/stats/namespace.pyi +5 -2
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/stats/parser.py +2 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/transactions/namespace.pyi +6 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/transactions/parser.py +2 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/upcoming_matches/models.py +8 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/upcoming_matches/namespace.pyi +6 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/upcoming_matches/parser.py +27 -11
- vlrdevapi-3.0.0/src/vlrdevapi/_utils/pagination.py +78 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_utils/team_enrichment.py +6 -5
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_utils/team_parsing.py +1 -1
- vlrdevapi-3.0.0/src/vlrdevapi/_utils/text.py +50 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/commons/datetime.py +1 -3
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/commons/timezone.py +1 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/exceptions.py +6 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/fetcher.py +11 -2
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/validators.py +21 -12
- vlrdevapi-3.0.0/uv.lock +1165 -0
- vlrdevapi-2.4.0/PKG-INFO +0 -226
- vlrdevapi-2.4.0/README.md +0 -178
- vlrdevapi-2.4.0/SECURITY.md +0 -9
- vlrdevapi-2.4.0/src/vlrdevapi/_series/economy/models.py +0 -85
- vlrdevapi-2.4.0/src/vlrdevapi/_series/economy/parser.py +0 -144
- vlrdevapi-2.4.0/src/vlrdevapi/_series/info/__init__.py +0 -4
- vlrdevapi-2.4.0/src/vlrdevapi/_series/vods/__init__.py +0 -4
- vlrdevapi-2.4.0/src/vlrdevapi/_series/vods/models.py +0 -28
- vlrdevapi-2.4.0/src/vlrdevapi/_series/vods/parser.py +0 -30
- vlrdevapi-2.4.0/src/vlrdevapi/_utils/pagination.py +0 -37
- vlrdevapi-2.4.0/uv.lock +0 -1049
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/.gitattributes +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/.github/workflows/cleanup-caches.yml +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/.github/workflows/publish.yml +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/.github/workflows/test.yml +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/.gitignore +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/.python-version +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/CONTRIBUTING.md +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/LICENCE +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_cache.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/_common.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/info/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/info/models.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/info/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/list/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/list/models.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/list/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/matches/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/stages/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/stages/models.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/stages/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/standings/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/standings/models.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/standings/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/teams/__init__.py +1 -1
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/teams/models.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_event/teams/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_matches/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_matches/completed/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_matches/completed/models.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_matches/completed/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_matches/live/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_matches/live/models.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_matches/live/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_matches/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_matches/upcoming/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_matches/upcoming/models.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_matches/upcoming/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_news/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_news/article/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_news/article/models.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_news/article/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_news/article/namespace.pyi +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_news/list/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_news/list/models.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_news/list/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_news/list/namespace.pyi +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_news/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_news/namespace.pyi +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/agents/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/agents/models.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/agents/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/info/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/matches/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/matches/models.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/matches/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/profile/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/profile/models.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/profile/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/teams/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/teams/models.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_player/teams/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/info/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/performance/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/performance/models.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/performance/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/players/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/players/models.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/players/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_series/rounds/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/completed_matches/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/info/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/info/models.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/placements/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/placements/models.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/placements/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/roster/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/roster/models.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/roster/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/stats/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/stats/models.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/transactions/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/transactions/models.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/transactions/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/upcoming_matches/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_team/upcoming_matches/namespace.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_utils/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/_utils/paths.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/commons/__init__.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/commons/countries.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/commons/mappings.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/commons/prizes.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/commons/regions.py +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/src/vlrdevapi/py.typed +0 -0
- {vlrdevapi-2.4.0 → vlrdevapi-3.0.0}/wrangler.jsonc +0 -0
|
@@ -24,36 +24,26 @@ jobs:
|
|
|
24
24
|
- name: Install package
|
|
25
25
|
run: uv sync --group dev
|
|
26
26
|
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
|
|
30
|
-
# missing, so the check is correct even with a partially-stale cache.
|
|
31
|
-
- name: Run MDX examples check (main, live)
|
|
32
|
-
if: github.ref_name == 'main'
|
|
33
|
-
run: uv run scripts/check_mdx_examples.py --live
|
|
34
|
-
|
|
35
|
-
# actions/cache v6.1.0, pinned to a reviewed commit SHA.
|
|
36
|
-
- name: Restore fixture cache (branch)
|
|
27
|
+
# Restore fixture cache scoped to the current ref (branch or main) and version prefix (v3).
|
|
28
|
+
# This ensures caches are never shared across unrelated branches or older versions.
|
|
29
|
+
- name: Restore fixture cache
|
|
37
30
|
id: mdx-fixtures
|
|
38
|
-
if: github.ref_name != 'main'
|
|
39
31
|
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
|
|
40
32
|
with:
|
|
41
33
|
path: fixtures.tar.gz
|
|
42
|
-
key: mdx-fixtures-${{ github.ref_name }}-run-${{ github.run_id }}
|
|
34
|
+
key: mdx-fixtures-v3-${{ github.ref_name }}-run-${{ github.run_id }}
|
|
43
35
|
restore-keys: |
|
|
44
|
-
mdx-fixtures-${{ github.ref_name }}-
|
|
36
|
+
mdx-fixtures-v3-${{ github.ref_name }}-
|
|
45
37
|
|
|
46
|
-
- name: Unpack fixtures
|
|
47
|
-
if: github.ref_name != 'main'
|
|
38
|
+
- name: Unpack fixtures
|
|
48
39
|
run: |
|
|
49
40
|
if [ -f fixtures.tar.gz ]; then
|
|
50
41
|
mkdir -p .cache
|
|
51
42
|
tar -C .cache -xzf fixtures.tar.gz
|
|
52
43
|
fi
|
|
53
44
|
|
|
54
|
-
- name: Check fixture cache age (
|
|
45
|
+
- name: Check fixture cache age (2h TTL)
|
|
55
46
|
id: cache-age
|
|
56
|
-
if: github.ref_name != 'main'
|
|
57
47
|
run: |
|
|
58
48
|
matched="${{ steps.mdx-fixtures.outputs.cache-matched-key }}"
|
|
59
49
|
now=$(date +%s)
|
|
@@ -73,8 +63,7 @@ jobs:
|
|
|
73
63
|
fi
|
|
74
64
|
echo "now=$now" >> "$GITHUB_OUTPUT"
|
|
75
65
|
|
|
76
|
-
- name: Run MDX examples check
|
|
77
|
-
if: github.ref_name != 'main'
|
|
66
|
+
- name: Run MDX examples check
|
|
78
67
|
run: |
|
|
79
68
|
if [ "${{ steps.cache-age.outputs.fresh }}" == "true" ]; then
|
|
80
69
|
uv run scripts/check_mdx_examples.py --skip-warm
|
|
@@ -84,8 +73,8 @@ jobs:
|
|
|
84
73
|
|
|
85
74
|
# always(): a run that fails validation still saved its warm fixtures,
|
|
86
75
|
# so the next fix commit restores and validates fast instead of warming.
|
|
87
|
-
- name: Package fixtures
|
|
88
|
-
if: always() &&
|
|
76
|
+
- name: Package fixtures
|
|
77
|
+
if: always() && steps.cache-age.outputs.fresh == 'false'
|
|
89
78
|
run: |
|
|
90
79
|
mkdir -p .cache/mdx-html
|
|
91
80
|
if [ -n "$(ls -A .cache/mdx-html)" ]; then
|
|
@@ -94,9 +83,9 @@ jobs:
|
|
|
94
83
|
rm -f fixtures.tar.gz
|
|
95
84
|
fi
|
|
96
85
|
|
|
97
|
-
- name: Save fixture cache
|
|
98
|
-
if: always() &&
|
|
86
|
+
- name: Save fixture cache
|
|
87
|
+
if: always() && steps.cache-age.outputs.fresh == 'false'
|
|
99
88
|
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9
|
|
100
89
|
with:
|
|
101
90
|
path: fixtures.tar.gz
|
|
102
|
-
key: mdx-fixtures-${{ github.ref_name }}-${{ steps.cache-age.outputs.now }}
|
|
91
|
+
key: mdx-fixtures-v3-${{ github.ref_name }}-${{ steps.cache-age.outputs.now }}
|
vlrdevapi-3.0.0/.nvmrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
26.10.0
|
|
@@ -6,10 +6,11 @@ build:
|
|
|
6
6
|
python: latest
|
|
7
7
|
jobs:
|
|
8
8
|
install:
|
|
9
|
-
- pip install
|
|
9
|
+
- pip install uv
|
|
10
|
+
- uv sync --group dev
|
|
10
11
|
build:
|
|
11
12
|
html:
|
|
12
|
-
- cd docs-py && zensical build
|
|
13
|
+
- cd docs-py && uv run zensical build
|
|
13
14
|
post_build:
|
|
14
15
|
- mkdir -p $READTHEDOCS_OUTPUT/html/
|
|
15
16
|
- cp --recursive docs-py/site/* $READTHEDOCS_OUTPUT/html/
|
|
@@ -5,6 +5,163 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
7
|
|
|
8
|
+
## [3.0.0] - 2026-10-23
|
|
9
|
+
|
|
10
|
+
### Breaking
|
|
11
|
+
|
|
12
|
+
- **`BuyType` re-tiered to match vlr.gg** — the economy tab no longer uses
|
|
13
|
+
its old four spend tiers. `SEMI_ECO` and `SEMI_BUY` are removed and the
|
|
14
|
+
remaining tiers follow VLR's current categories based on total team
|
|
15
|
+
spend: `ECO` (under 10k), `HALF_BUY` (10k–18k), and `FULL_BUY` (18k+).
|
|
16
|
+
A new `PISTOL` member marks pistol-round buys (previously reported as
|
|
17
|
+
`ECO`). Code switching on `BuyType.SEMI_ECO` / `BuyType.SEMI_BUY` needs
|
|
18
|
+
updating; string values are `"Pistol"`, `"Eco"`, `"Half-buy"`,
|
|
19
|
+
`"Full-buy"`.
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- **Buy-type matrix** — `EconomyData` now carries the economy tab's
|
|
24
|
+
buy-type matrix as `buy_matrix_team1` / `buy_matrix_team2`
|
|
25
|
+
(`TeamBuyMatrix`): the Pistol / Conv. / Bonus summary and the
|
|
26
|
+
`On Eco` / `On Half buy` / `On Full buy` records
|
|
27
|
+
(`BuyTierRecord.vs_eco` / `vs_half` / `vs_full`), each a
|
|
28
|
+
`won`/`total` `EconScore`. Unplayed matchups are `None`.
|
|
29
|
+
`series.economy(game_id="all")` on the parser also now returns the
|
|
30
|
+
all-maps aggregate matrix instead of an empty result.
|
|
31
|
+
- **Convenience accessors** — flat summary shortcuts
|
|
32
|
+
(`pistol_team1` / `converted_team1` / `bonus_team1` and the
|
|
33
|
+
`_team2` counterparts), `full_buy` / `half_buy` / `eco` aliases on
|
|
34
|
+
`TeamBuyMatrix`, and a combined `total` on `BuyTierRecord` for the
|
|
35
|
+
overall won/total on a tier regardless of the opponent's buy type.
|
|
36
|
+
- **Round economy in `series.rounds`** — `RoundData` now carries the
|
|
37
|
+
per-round economy from the economy tab: `bank_team1`/`bank_team2`,
|
|
38
|
+
`spent_team1`/`spent_team2`, `buy_type_team1`/`buy_type_team2`, and
|
|
39
|
+
`is_pistol_round`. `series.rounds` fetches and merges the economy tab
|
|
40
|
+
automatically (economy fields stay `None`/empty when that page is
|
|
41
|
+
unavailable), making it the single round-by-round source alongside
|
|
42
|
+
`win_type` and the winner's `side`.
|
|
43
|
+
- **Series replay (logs tab)** — new `series.replay(series_id, game_id)`
|
|
44
|
+
returning the per-round kill-feed timeline (`ReplayData` /
|
|
45
|
+
`ReplayRound` / `ReplayEvent`): events typed by the `ReplayEventType`
|
|
46
|
+
enum (`KILL`, `PLANT`, `DEFUSE`, plus derived `BOOM` detonation and
|
|
47
|
+
`RESURRECT` events with `derived=True`, since vlr.gg logs neither as
|
|
48
|
+
feed rows), round clocks in both display (`clock`) and numeric
|
|
49
|
+
(`seconds`) form, kill cause (weapon or ability, e.g. `Sheriff`,
|
|
50
|
+
`Overdrive`, `Tour de Force`, `Spike`), killer/victim positions with
|
|
51
|
+
distance in minimap units, spike sites, and per-event alive snapshots
|
|
52
|
+
(name, agent, team, side, minimap coordinates, facing angle). Each
|
|
53
|
+
`ReplayRound` also includes `loadouts` (`list[PlayerRoundLoadout]`)
|
|
54
|
+
and the `loadout_for(player)` helper, capturing every player's
|
|
55
|
+
equipped weapon at round start, armor (supporting `No armor`,
|
|
56
|
+
`Light armor`, `Heavy armor`, and `Regen Shield`), and credits
|
|
57
|
+
left / spent in the buy phase. Real vlr.gg team and player IDs are
|
|
58
|
+
resolved from the game's overview tab
|
|
59
|
+
(one extra request, `team1_id`/`team2_id` and `player_id` fields) and
|
|
60
|
+
matched strictly within each player's team so duplicate names never
|
|
61
|
+
cross teams; unplayed maps or maps without round data return an
|
|
62
|
+
empty timeline gracefully.
|
|
63
|
+
- **Series head-to-head history** — `SeriesInfo.head_to_head` exposes
|
|
64
|
+
previous meetings between the two teams, parsed from the same overview
|
|
65
|
+
page. Each `SeriesHeadToHeadMatch` includes the series ID/URL, event,
|
|
66
|
+
stage, date, both team names/scores, and which side won.
|
|
67
|
+
- **Series streams in `series.vods()`** — `SeriesVods.streams` now contains
|
|
68
|
+
live broadcasts and watch-party streams alongside the existing `vods`
|
|
69
|
+
list. Each `SeriesStream` exposes the platform, channel, URL, stream
|
|
70
|
+
type, and country code. `SeriesVod` also gains `platform`, `map_number`,
|
|
71
|
+
and `start_seconds`.
|
|
72
|
+
- **Player total winnings** — `PlayerInfo.total_winnings` and
|
|
73
|
+
`total_winnings_currency` now expose the total from the player's Event
|
|
74
|
+
Placements card.
|
|
75
|
+
- **New `player.placements()` namespace** — returns `PlayerPlacements` with
|
|
76
|
+
individual `PlayerEventPlacement` rows (event, year, stage, placement,
|
|
77
|
+
prize, team) and the player's total winnings.
|
|
78
|
+
- **New grand-final fixtures** — series 130685 (LOUD vs OpTic, Champions
|
|
79
|
+
2022 GF) and 754737 (LOUD vs Vitality, Champions 2026 GF) are now
|
|
80
|
+
covered by tests across economy, info/pick-bans, players, rounds, and
|
|
81
|
+
performance parsers.
|
|
82
|
+
|
|
83
|
+
### Fixed
|
|
84
|
+
|
|
85
|
+
- **`team.upcoming_matches()` no longer returns completed matches** — the
|
|
86
|
+
parser now scopes its search to the heading's section wrapper instead of
|
|
87
|
+
the whole team-summary column, so "Recent Results" is excluded.
|
|
88
|
+
- **`series.info()` on upcoming/live series** — `best_of` is now read from
|
|
89
|
+
whichever match-header note contains the format (vlr.gg renders the
|
|
90
|
+
countdown twice before `BoN`), and `TBD` map tabs are no longer marked
|
|
91
|
+
`played`.
|
|
92
|
+
- **`team.completed_matches()` pagination** — added `limit` (default `50`)
|
|
93
|
+
and `return_all`; extra pages are fetched only when the requested limit
|
|
94
|
+
needs them. `TeamCompletedMatches.has_next_page` reports whether more
|
|
95
|
+
matches exist beyond the returned results.
|
|
96
|
+
- **Team match `stage`/`bracket`** — both fields are now parsed separately
|
|
97
|
+
from the team matches page (e.g. `stage="Playoffs"`, `bracket="LBF"`),
|
|
98
|
+
and enrichment no longer concatenates them into `"Playoffs - LBF"`.
|
|
99
|
+
- **Parser whitespace** — shared `normalize_whitespace()` collapses raw tabs,
|
|
100
|
+
newlines, and repeated spaces in parsed event/stage/bracket/role values
|
|
101
|
+
instead of leaving values such as `"Playoffs ⋅\n\t\t\tLBF"`.
|
|
102
|
+
- **`events.matches()` team countries** — `MatchTeam` now exposes
|
|
103
|
+
`country_name`, parsed from the team flag on the event matches page.
|
|
104
|
+
- **Thread-local HTTP client lifecycle** — parallel requests now reuse
|
|
105
|
+
thread-local clients and close every client after fetching or enrichment,
|
|
106
|
+
reducing client-creation overhead and preventing resource leaks.
|
|
107
|
+
|
|
108
|
+
### Changed
|
|
109
|
+
|
|
110
|
+
- **`RoundData.win_type` is now a `RoundWinType` enum** instead of a
|
|
111
|
+
human-readable string. Use `round.win_type.full_name` for display text and
|
|
112
|
+
`round.win_type.value` (`"elimination"`, `"defuse"`, `"spike_detonation"`,
|
|
113
|
+
`"time_expired"`) for the raw value.
|
|
114
|
+
|
|
115
|
+
### Documentation
|
|
116
|
+
|
|
117
|
+
- Series economy reference updated for the new `BuyType` values,
|
|
118
|
+
buy-matrix fields, and nested models; series rounds reference updated
|
|
119
|
+
for the merged per-round economy fields; new series replay reference
|
|
120
|
+
page for the kill-feed timeline module.
|
|
121
|
+
- Updated the `team.completed_matches`, `team.upcoming_matches`,
|
|
122
|
+
`events.matches`, and `series.rounds` references for `bracket`,
|
|
123
|
+
`country_name`, and the `RoundWinType` enum.
|
|
124
|
+
- Updated `series.info`, `series.vods`, and `player.info`, and added a
|
|
125
|
+
`player.placements` reference for head-to-head history, streams, VOD
|
|
126
|
+
metadata, and event placements.
|
|
127
|
+
|
|
128
|
+
## [2.4.1] - 2026-10-17
|
|
129
|
+
|
|
130
|
+
### Fixed
|
|
131
|
+
|
|
132
|
+
- **Series players/stats parsing** — newer vlr.gg overview tables add a
|
|
133
|
+
dedicated `.mod-agents` cell before the stat columns. Stat cells are now
|
|
134
|
+
mapped dynamically around that column, and agents are read from the new
|
|
135
|
+
cell. This fixes `SideStats` validation errors and misaligned values
|
|
136
|
+
(rating, ACS, KDA, KAST, ADR, HS%, first kills/deaths).
|
|
137
|
+
- **Series economy parsing** — the round-by-round economy grid now uses the
|
|
138
|
+
newer `.vlr-rounds.ecr` markup (`.ecr-bank`, `.ecc-c`, `.ecc-sq`). Banks,
|
|
139
|
+
spends, buy types, and round winners are read from it, with the legacy
|
|
140
|
+
`.wf-table-inset.mod-econ` table kept as a fallback.
|
|
141
|
+
- **Series VODs parsing** — VODs are now read from the newer `.sm-vods`
|
|
142
|
+
module (`.sm-vod-name` labels, `a.sm-ext` links), keeping the legacy
|
|
143
|
+
`.match-vods` container as a fallback.
|
|
144
|
+
- **Series game map names** — the game header now renders the duration as a
|
|
145
|
+
sibling of the map name. The map name is read from `.map-name`, so the
|
|
146
|
+
duration is no longer concatenated (e.g. `Pearl` instead of `Pearl35:48`).
|
|
147
|
+
|
|
148
|
+
### Changed
|
|
149
|
+
|
|
150
|
+
- **Series economy team matching** — team/abbreviation resolution is now
|
|
151
|
+
case-insensitive, so team IDs resolve for pages that render short tags.
|
|
152
|
+
- **HTML parsing backend** — parsing now uses selectolax's Lexbor engine
|
|
153
|
+
(`selectolax.lexbor`) instead of the discontinued Modest engine
|
|
154
|
+
(`selectolax.parser`), which selectolax removed in 1.0. This is an internal
|
|
155
|
+
change: the public API, CSS selectors, and parsed output are unchanged.
|
|
156
|
+
- **Dependencies** — raised the `selectolax` minimum to `>=1.0.0` and moved
|
|
157
|
+
`pydantic` to the 2.14 series.
|
|
158
|
+
|
|
159
|
+
### Documentation
|
|
160
|
+
|
|
161
|
+
- **Changelog** — this release is mirrored across `CHANGELOG.md`, the
|
|
162
|
+
ReadTheDocs changelog (`docs-py/docs/changelog.md`), and the official
|
|
163
|
+
site changelog (`official-docs/app/(home)/changelog/page.tsx`).
|
|
164
|
+
|
|
8
165
|
## [2.4.0] - 2026-08-19
|
|
9
166
|
|
|
10
167
|
### Added
|
|
@@ -279,6 +436,8 @@ The API surface, module structure, and type system are all new.
|
|
|
279
436
|
- `aiohttp` and `asyncio` dependencies.
|
|
280
437
|
- v1.x match/event/team parsing modules.
|
|
281
438
|
|
|
439
|
+
[3.0.0]: https://github.com/Vanshbordia/vlrdevapi/compare/v2.4.1...v3.0.0
|
|
440
|
+
[2.4.1]: https://github.com/Vanshbordia/vlrdevapi/compare/v2.4.0...v2.4.1
|
|
282
441
|
[2.4.0]: https://github.com/Vanshbordia/vlrdevapi/compare/v2.3.0...v2.4.0
|
|
283
442
|
[2.3.0]: https://github.com/Vanshbordia/vlrdevapi/compare/v2.2.0...v2.3.0
|
|
284
443
|
[2.2.0]: https://github.com/Vanshbordia/vlrdevapi/compare/v2.1.0...v2.2.0
|
|
@@ -15,5 +15,6 @@ diverse, inclusive, and healthy community.
|
|
|
15
15
|
## Enforcement
|
|
16
16
|
|
|
17
17
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
18
|
-
reported to the project maintainers
|
|
18
|
+
reported to the project maintainers via the repository at
|
|
19
|
+
https://github.com/vanshbordia/vlrdevapi. All complaints
|
|
19
20
|
will be reviewed and investigated.
|
vlrdevapi-3.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: vlrdevapi
|
|
3
|
+
Version: 3.0.0
|
|
4
|
+
Summary: A Python library to scrape data from vlr.gg
|
|
5
|
+
Project-URL: Homepage, https://vlrdevapi.pages.dev/
|
|
6
|
+
Project-URL: Repository, https://github.com/Vanshbordia/vlrdevapi
|
|
7
|
+
Project-URL: Documentation, https://vlrdevapi.pages.dev/docs/
|
|
8
|
+
License: MIT License
|
|
9
|
+
|
|
10
|
+
Copyright (c) 2026 Vansh Bordia
|
|
11
|
+
|
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
13
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
14
|
+
in the Software without restriction, including without limitation the rights
|
|
15
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
16
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
17
|
+
furnished to do so, subject to the following conditions:
|
|
18
|
+
|
|
19
|
+
The above copyright notice and this permission notice shall be included in all
|
|
20
|
+
copies or substantial portions of the Software.
|
|
21
|
+
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
|
+
SOFTWARE.
|
|
29
|
+
License-File: LICENCE
|
|
30
|
+
Keywords: api,esports,python,scraper,sdk,valorant,valorant esports,vct,vlr.gg,vlrgg
|
|
31
|
+
Classifier: Development Status :: 3 - Alpha
|
|
32
|
+
Classifier: Intended Audience :: Developers
|
|
33
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
34
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
38
|
+
Classifier: Topic :: Games/Entertainment
|
|
39
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
40
|
+
Requires-Python: >=3.11
|
|
41
|
+
Requires-Dist: httpx>=0.28.1
|
|
42
|
+
Requires-Dist: pydantic>=2.14.1
|
|
43
|
+
Requires-Dist: selectolax>=1.0.0
|
|
44
|
+
Provides-Extra: test
|
|
45
|
+
Requires-Dist: pytest-cov>=7.1.0; extra == 'test'
|
|
46
|
+
Requires-Dist: pytest>=9.1.1; extra == 'test'
|
|
47
|
+
Requires-Dist: respx>=0.23.1; extra == 'test'
|
|
48
|
+
Description-Content-Type: text/markdown
|
|
49
|
+
|
|
50
|
+
<div align="center">
|
|
51
|
+
|
|
52
|
+
<img src="official-docs/public/logo.png" width="120" alt="vlrdevapi logo">
|
|
53
|
+
|
|
54
|
+
# vlrdevapi
|
|
55
|
+
|
|
56
|
+
**The modern, type-safe Python library for VLR.gg Valorant esports data**
|
|
57
|
+
|
|
58
|
+
[](https://pypi.org/project/vlrdevapi/)
|
|
59
|
+
[](https://pypi.org/project/vlrdevapi/)
|
|
60
|
+
[](https://opensource.org/licenses/MIT)
|
|
61
|
+
[](https://vlrdevapi.pages.dev/docs/)
|
|
62
|
+
|
|
63
|
+
[Documentation](https://vlrdevapi.pages.dev/docs/) · [Quickstart](https://vlrdevapi.pages.dev/docs/quickstart/) · [API Reference](https://vlrdevapi.pages.dev/docs/reference/) · [Guides](https://vlrdevapi.pages.dev/guides/) · [Changelog](https://vlrdevapi.pages.dev/changelog/) · [PyPI](https://pypi.org/project/vlrdevapi/)
|
|
64
|
+
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
**vlrdevapi** is a high-performance, type-safe Python client for extracting and analyzing Valorant esports data from [VLR.gg](https://www.vlr.gg/). Built for competitive analysts, data scientists, Discord bot creators, and esports engineers, it delivers structured [Pydantic](https://docs.pydantic.dev/) models with full type hinting, built-in rate limiting, automatic retries, and comprehensive coverage across all VLR.gg entities.
|
|
70
|
+
|
|
71
|
+
Whether you need live match tickers, tournament brackets, historical player ratings, round-by-round economy buy matrices, or 2D minimap kill-feed replay timelines with player loadouts, **vlrdevapi** provides a clean, idiomatic interface.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Highlights
|
|
76
|
+
|
|
77
|
+
- **Complete Valorant Esports Coverage** — Tournaments, match schedules, live scoreboards, player careers, team rosters, roster transactions, and esports news.
|
|
78
|
+
- **2D Kill-Feed Replay Timelines** — Spatial `(x, y)` kill coordinates, viewing angles, kill distances, plant/defuse events, spike detonations (`boom`), resurrections, alive player snapshots, and buy-phase **player loadouts** (weapons, shields, spent credits, remaining bank).
|
|
79
|
+
- **Round-by-Round Economy** — Full team buy matrices (`loadout_value`, `spent`, `bank`, buy classifications like `Eco`, `Anti-eco`, `Semi-buy`, `Semi-rifle`, and `Full buy`).
|
|
80
|
+
- **Strictly Typed Pydantic Models** — Every endpoint returns validated models with full field annotations, descriptive docstrings, and IDE autocompletion.
|
|
81
|
+
- **Production-Ready Reliability** — Built-in token-bucket rate limiter, exponential backoff retries, thread-safe connection pooling, and LRU-cached enrichment.
|
|
82
|
+
- **Flexible Access Patterns** — Use lightweight module-level calls (`vlrdevapi.player.info(...)`), curried ID chaining (`vlrdevapi.player(11225).info()`), or a managed context manager (`with VLRClient() as client:`).
|
|
83
|
+
- **Timezone Awareness** — Seamlessly convert match schedules and timestamps into any target timezone via Python's standard `zoneinfo`.
|
|
84
|
+
- **Managed with [uv](https://docs.astral.sh/uv/)** — Blazing fast dependency resolution and testing workflows.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Installation
|
|
89
|
+
|
|
90
|
+
Install `vlrdevapi` using [uv](https://docs.astral.sh/uv/) (recommended) or `pip`:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Using uv (recommended)
|
|
94
|
+
uv add vlrdevapi
|
|
95
|
+
|
|
96
|
+
# Using pip
|
|
97
|
+
pip install vlrdevapi
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
> **Requirements:** Python 3.11 or higher.
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Quickstart
|
|
105
|
+
|
|
106
|
+
### 1. Direct Module-Level Access (Zero Setup)
|
|
107
|
+
|
|
108
|
+
Fetch data immediately without instantiating a client:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
import vlrdevapi
|
|
112
|
+
|
|
113
|
+
# Get player profile and country
|
|
114
|
+
player = vlrdevapi.player.info(player_id=11225)
|
|
115
|
+
print(f"Player: {player.name} ({player.country})")
|
|
116
|
+
|
|
117
|
+
# Get series overview
|
|
118
|
+
series = vlrdevapi.series.info(series_id=542272)
|
|
119
|
+
print(f"Match: {series.team1.name} vs {series.team2.name} - Score: {series.score1}:{series.score2}")
|
|
120
|
+
|
|
121
|
+
# Get event details
|
|
122
|
+
event = vlrdevapi.event.info(event_id=2863)
|
|
123
|
+
print(f"Event: {event.name} ({event.start_date} to {event.end_date})")
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 2. Curried Method Chaining
|
|
127
|
+
|
|
128
|
+
Bind an ID once, then query multiple sub-methods without repeating the identifier:
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
import vlrdevapi
|
|
132
|
+
|
|
133
|
+
# Bind team 2593 (FNATIC) once
|
|
134
|
+
fnc = vlrdevapi.team(2593)
|
|
135
|
+
|
|
136
|
+
info = fnc.info()
|
|
137
|
+
print(f"{info.name} [{info.tag}] - Country: {info.country}")
|
|
138
|
+
|
|
139
|
+
roster = fnc.roster()
|
|
140
|
+
print(f"Active Players: {[p.ign for p in roster.players]}")
|
|
141
|
+
|
|
142
|
+
placements = fnc.placements()
|
|
143
|
+
print(f"Total Prize Earnings: {placements.total_winnings_currency}{placements.total_winnings:,}")
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### 3. Managed Client Session (`VLRClient`)
|
|
147
|
+
|
|
148
|
+
For production applications, high-throughput scripts, or custom concurrency tuning, use `VLRClient`:
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
from vlrdevapi import VLRClient
|
|
152
|
+
|
|
153
|
+
with VLRClient(timeout=30, requests_per_second=8, max_retries=3) as client:
|
|
154
|
+
# Live matches ticker
|
|
155
|
+
live_matches = client.matches.live()
|
|
156
|
+
for m in live_matches.matches:
|
|
157
|
+
print(f"LIVE: {m.team1.name} vs {m.team2.name} ({m.event})")
|
|
158
|
+
|
|
159
|
+
# Series performance & economy
|
|
160
|
+
series = client.series(542272)
|
|
161
|
+
econ = series.economy(game_id=1)
|
|
162
|
+
print(f"Map 1 Rounds Analyzed: {len(econ.rounds)}")
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## API Overview & Reference
|
|
168
|
+
|
|
169
|
+
| Module | Key Methods | Description | Official Docs |
|
|
170
|
+
|:---|:---|:---|:---|
|
|
171
|
+
| **[Matches](https://vlrdevapi.pages.dev/docs/reference/matches/)** | `upcoming()`, `live()`, `completed()` | Live scores, upcoming schedules, and paginated match history | [Docs →](https://vlrdevapi.pages.dev/docs/reference/matches/) |
|
|
172
|
+
| **[Series](https://vlrdevapi.pages.dev/docs/reference/series/)** | `info()`, `replay()`, `economy()`, `players()`, `rounds()`, `vods()`, `performance()` | Deep map analytics, kill-feed timeline, buy matrices, player stats, and streams | [Docs →](https://vlrdevapi.pages.dev/docs/reference/series/) |
|
|
173
|
+
| **[Players](https://vlrdevapi.pages.dev/docs/reference/player/)** | `info()`, `profile()`, `agents()`, `teams()`, `matches()`, `placements()` | Historical ratings (ACS, K/D, ADR, KAST), agent pools, career history, and placements | [Docs →](https://vlrdevapi.pages.dev/docs/reference/player/) |
|
|
174
|
+
| **[Teams](https://vlrdevapi.pages.dev/docs/reference/team/)** | `info()`, `roster()`, `placements()`, `transactions()`, `completed_matches()`, `upcoming_matches()` | Active rosters, staff, roster transfers, historical match records, and tournament earnings | [Docs →](https://vlrdevapi.pages.dev/docs/reference/team/) |
|
|
175
|
+
| **[Events](https://vlrdevapi.pages.dev/docs/reference/events/)** | `info()`, `stages()`, `matches()`, `standings()`, `teams()`, `list()` | Tournament brackets, group/playoff stages, standings, prize pools, and participating teams | [Docs →](https://vlrdevapi.pages.dev/docs/reference/events/) |
|
|
176
|
+
| **[News](https://vlrdevapi.pages.dev/docs/reference/news/)** | `list()`, `article()` | VLR.gg editorial articles, breaking roster news, author details, and full Markdown content | [Docs →](https://vlrdevapi.pages.dev/docs/reference/news/) |
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Code Examples
|
|
181
|
+
|
|
182
|
+
### 1. Spatial Replay Timeline & Round Loadouts
|
|
183
|
+
|
|
184
|
+
Inspect round-by-round kill events with 2D minimap locations, viewing angles, distances, and player equipment:
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
import vlrdevapi
|
|
188
|
+
|
|
189
|
+
# Fetch replay timeline for Game 3 of a series (Sunset)
|
|
190
|
+
replay = vlrdevapi.series.replay(series_id=754737, game_id=283288)
|
|
191
|
+
round_1 = replay.round(1)
|
|
192
|
+
|
|
193
|
+
if round_1:
|
|
194
|
+
print(f"Round 1 Attacking Side: {round_1.attacking}")
|
|
195
|
+
|
|
196
|
+
# Check buy-phase loadout for a player
|
|
197
|
+
loadout = round_1.loadout_for("Derke")
|
|
198
|
+
if loadout:
|
|
199
|
+
print(f"Derke: Weapon={loadout.weapon}, Armor={loadout.armor}, Spent=${loadout.spent}")
|
|
200
|
+
|
|
201
|
+
# Iterate through kill events
|
|
202
|
+
for event in round_1.events:
|
|
203
|
+
if event.type.value == "kill":
|
|
204
|
+
killer = event.actor.name if event.actor else "World"
|
|
205
|
+
victim = event.victim.name if event.victim else "Unknown"
|
|
206
|
+
dist = f"{event.distance_units:.1f}u" if event.distance_units else "N/A"
|
|
207
|
+
print(f" [{event.clock}] {killer} killed {victim} with {event.cause} (dist: {dist})")
|
|
208
|
+
if event.pos_x is not None:
|
|
209
|
+
print(f" Victim pos: ({event.pos_x}, {event.pos_y}) | Killer pos: ({event.from_x}, {event.from_y})")
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Learn more in the [Series Replay Documentation](https://vlrdevapi.pages.dev/docs/reference/series/replay/).
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
### 2. Round Economy & Team Buy Matrices
|
|
217
|
+
|
|
218
|
+
Analyze team spending, bank reserves, and buy types across rounds:
|
|
219
|
+
|
|
220
|
+
```python
|
|
221
|
+
import vlrdevapi
|
|
222
|
+
|
|
223
|
+
economy = vlrdevapi.series.economy(series_id=754737, game_id=283288)
|
|
224
|
+
|
|
225
|
+
for r in economy.rounds[:5]:
|
|
226
|
+
winner_name = r.winner.name if r.winner else "Unknown"
|
|
227
|
+
print(f"Round {r.round_number}: Winner = {winner_name}")
|
|
228
|
+
print(f" {economy.team1}: {r.buy_type_team1} (Spent: ${r.spent_team1:,}, Bank: ${r.bank_team1:,})")
|
|
229
|
+
print(f" {economy.team2}: {r.buy_type_team2} (Spent: ${r.spent_team2:,}, Bank: ${r.bank_team2:,})")
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Learn more in the [Series Economy Documentation](https://vlrdevapi.pages.dev/docs/reference/series/economy/).
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
### 3. Player Career Statistics & Agent Pools
|
|
237
|
+
|
|
238
|
+
Extract ACS, K/D, KAST, and ADR broken down by agent:
|
|
239
|
+
|
|
240
|
+
```python
|
|
241
|
+
import vlrdevapi
|
|
242
|
+
|
|
243
|
+
# Query player agent stats over the last 60 days
|
|
244
|
+
agent_stats = vlrdevapi.player.agents(player_id=11225, timespan="60d")
|
|
245
|
+
|
|
246
|
+
for a in agent_stats.agents[:4]:
|
|
247
|
+
print(f"{a.agent:<10} | Pick Rate: {a.use} | Rating: {a.rating} | ACS: {a.acs} | K/D: {a.kd}")
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Learn more in the [Player Reference Documentation](https://vlrdevapi.pages.dev/docs/reference/player/).
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
### 4. Tournament Brackets & Standings
|
|
255
|
+
|
|
256
|
+
Fetch event stages, match schedules, and final prize distributions:
|
|
257
|
+
|
|
258
|
+
```python
|
|
259
|
+
import vlrdevapi
|
|
260
|
+
|
|
261
|
+
event_id = 2863 # e.g., Champions 2026
|
|
262
|
+
event = vlrdevapi.event(event_id)
|
|
263
|
+
|
|
264
|
+
# Event stages (Group Stage, Playoffs, etc.)
|
|
265
|
+
for stage in event.stages():
|
|
266
|
+
print(f"Stage: {stage.name} (ID: {stage.id})")
|
|
267
|
+
|
|
268
|
+
# Final event standings & prize earnings
|
|
269
|
+
standings = event.standings()
|
|
270
|
+
for stage in standings.stages[:1]:
|
|
271
|
+
print(f"--- {stage.stage_name} ---")
|
|
272
|
+
for row in stage.standings[:3]:
|
|
273
|
+
team_name = row.team.name if row.team else "TBD"
|
|
274
|
+
prize = f"{row.prize_currency}{row.prize_money:,}" if row.prize_money else "N/A"
|
|
275
|
+
print(f" #{row.place}: {team_name} - Prize: {prize}")
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Learn more in the [Events Reference Documentation](https://vlrdevapi.pages.dev/docs/reference/events/).
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
### 5. News Articles with Full Markdown
|
|
283
|
+
|
|
284
|
+
Read VLR.gg editorial content formatted in clean GitHub-flavored Markdown:
|
|
285
|
+
|
|
286
|
+
```python
|
|
287
|
+
import vlrdevapi
|
|
288
|
+
|
|
289
|
+
# Get latest articles
|
|
290
|
+
feed = vlrdevapi.news(page=1)
|
|
291
|
+
latest = feed.news[0]
|
|
292
|
+
|
|
293
|
+
# Retrieve full article body
|
|
294
|
+
article = vlrdevapi.news.article(latest.id)
|
|
295
|
+
print(f"Title: {article.title}")
|
|
296
|
+
print(f"Author: {article.author} ({article.date})")
|
|
297
|
+
print(f"Length: {len(article.content_md):,} characters")
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Learn more in the [News Reference Documentation](https://vlrdevapi.pages.dev/docs/reference/news/).
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Configuration & Error Handling
|
|
305
|
+
|
|
306
|
+
### Rate Limiting & Concurrency
|
|
307
|
+
|
|
308
|
+
`vlrdevapi` includes sensible defaults (`4.0` requests per second) to respect VLR.gg servers. When using `VLRClient`, you can customize client settings:
|
|
309
|
+
|
|
310
|
+
```python
|
|
311
|
+
from zoneinfo import ZoneInfo
|
|
312
|
+
from vlrdevapi import VLRClient
|
|
313
|
+
|
|
314
|
+
client = VLRClient(
|
|
315
|
+
timeout=20, # Timeout per request (seconds)
|
|
316
|
+
requests_per_second=6, # Max rate limit
|
|
317
|
+
max_retries=4, # Exponential backoff retries
|
|
318
|
+
source_tz=ZoneInfo("America/New_York"), # Target timezone for schedules
|
|
319
|
+
)
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Typed Exceptions
|
|
323
|
+
|
|
324
|
+
Catch errors with specific, typed exception classes from `vlrdevapi.exceptions`:
|
|
325
|
+
|
|
326
|
+
```python
|
|
327
|
+
import vlrdevapi
|
|
328
|
+
from vlrdevapi.exceptions import (
|
|
329
|
+
NotFoundError,
|
|
330
|
+
RateLimitError,
|
|
331
|
+
RequestError,
|
|
332
|
+
ValidationError,
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
try:
|
|
336
|
+
player = vlrdevapi.player.info(player_id=99999999)
|
|
337
|
+
except NotFoundError:
|
|
338
|
+
print("Player not found on VLR.gg (404).")
|
|
339
|
+
except RateLimitError:
|
|
340
|
+
print("Exceeded VLR.gg rate limits. Please slow down requests.")
|
|
341
|
+
except ValidationError as e:
|
|
342
|
+
print(f"Invalid parameter passed: {e}")
|
|
343
|
+
except RequestError as e:
|
|
344
|
+
print(f"Network error occurred: {e}")
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## Documentation & Guides
|
|
350
|
+
|
|
351
|
+
Comprehensive documentation, tutorials, and deep-dives are available on the official documentation portal:
|
|
352
|
+
|
|
353
|
+
- **[Documentation Home](https://vlrdevapi.pages.dev/docs/)** — Complete getting-started guide and architectural overview.
|
|
354
|
+
- **[Quickstart Guide](https://vlrdevapi.pages.dev/docs/quickstart/)** — First queries in under two minutes.
|
|
355
|
+
- **[Series Replay Guide](https://vlrdevapi.pages.dev/docs/reference/series/replay/)** — Mapping 2D replay coordinates, viewing angles, and equipment.
|
|
356
|
+
- **[Series Economy Guide](https://vlrdevapi.pages.dev/docs/reference/series/economy/)** — Round spending and buy matrix mechanics.
|
|
357
|
+
- **[Guides & Tutorials](https://vlrdevapi.pages.dev/guides/)** — Real-world guides for Discord bots, Pandas analysis, and Polars pipelines.
|
|
358
|
+
- **[Frequently Asked Questions](https://vlrdevapi.pages.dev/faq/)** — Common questions on rate limits, IDs, and data structures.
|
|
359
|
+
- **[Changelog](https://vlrdevapi.pages.dev/changelog/)** — Version history and release notes.
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## Development
|
|
364
|
+
|
|
365
|
+
Contributions and bug reports are welcome! This repository uses `uv` for package management and testing:
|
|
366
|
+
|
|
367
|
+
```bash
|
|
368
|
+
# 1. Clone the repository
|
|
369
|
+
git clone https://github.com/Vanshbordia/vlrdevapi.git
|
|
370
|
+
cd vlrdevapi
|
|
371
|
+
|
|
372
|
+
# 2. Install dependencies with uv
|
|
373
|
+
uv sync --group dev
|
|
374
|
+
|
|
375
|
+
# 3. Run the unit test suite
|
|
376
|
+
uv run pytest tests/ -v
|
|
377
|
+
|
|
378
|
+
# 4. Run static type checking and linter
|
|
379
|
+
uv run ruff check src/ tests/
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
Please read our [Contributing Guide](CONTRIBUTING.md) and [Code of Conduct](CODE_OF_CONDUCT.md) before submitting pull requests.
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
386
|
+
## License
|
|
387
|
+
|
|
388
|
+
This project is licensed under the [MIT License](LICENCE).
|
|
389
|
+
|
|
390
|
+
---
|
|
391
|
+
|
|
392
|
+
## Disclaimer
|
|
393
|
+
|
|
394
|
+
`vlrdevapi` is an independent open-source library. It is not affiliated with, maintained, authorized, or endorsed by [VLR.gg](https://www.vlr.gg/) or [Riot Games](https://www.riotgames.com/). Valorant and all associated properties are trademarks or registered trademarks of Riot Games, Inc. Please use responsibly and respect VLR.gg's bandwidth and server infrastructure.
|