nyt-games 0.1.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.
@@ -0,0 +1,21 @@
1
+ # MIT License
2
+
3
+ Copyright (c) 2024 Joost Lekkerkerker
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,161 @@
1
+ Metadata-Version: 2.1
2
+ Name: nyt_games
3
+ Version: 0.1.0
4
+ Summary: Asynchronous Python client for NYT games.
5
+ Home-page: https://github.com/joostlek/python-nyt-games
6
+ License: MIT
7
+ Keywords: NYT games,api,async,client
8
+ Author: Joost Lekkerkerker
9
+ Author-email: joostlek@outlook.com
10
+ Maintainer: Joost Lekkerkerker
11
+ Maintainer-email: joostlek@outlook.com
12
+ Requires-Python: >=3.11,<4.0
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Framework :: AsyncIO
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Natural Language :: English
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Requires-Dist: aiohttp (>=3.0.0)
23
+ Requires-Dist: mashumaro (>=3.11,<4.0)
24
+ Requires-Dist: orjson (>=3.9.0)
25
+ Requires-Dist: yarl (>=1.6.0)
26
+ Project-URL: Bug Tracker, https://github.com/joostlek/python-nyt-games/issues
27
+ Project-URL: Changelog, https://github.com/joostlek/python-nyt-games/releases
28
+ Project-URL: Documentation, https://github.com/joostlek/python-nyt-games
29
+ Project-URL: Repository, https://github.com/joostlek/python-nyt-games
30
+ Description-Content-Type: text/markdown
31
+
32
+ # Python: NYT Games
33
+
34
+ [![GitHub Release][releases-shield]][releases]
35
+ [![Python Versions][python-versions-shield]][pypi]
36
+ ![Project Stage][project-stage-shield]
37
+ ![Project Maintenance][maintenance-shield]
38
+ [![License][license-shield]](LICENSE.md)
39
+
40
+ [![Build Status][build-shield]][build]
41
+ [![Code Coverage][codecov-shield]][codecov]
42
+
43
+ Asynchronous Python client for NYT Games.
44
+
45
+ ## About
46
+
47
+ This package allows you to fetch data from NYT Games.
48
+
49
+ ## Installation
50
+
51
+ ```bash
52
+ pip install nyt_games
53
+ ```
54
+
55
+ ## Changelog & Releases
56
+
57
+ This repository keeps a change log using [GitHub's releases][releases]
58
+ functionality. The format of the log is based on
59
+ [Keep a Changelog][keepchangelog].
60
+
61
+ Releases are based on [Semantic Versioning][semver], and use the format
62
+ of ``MAJOR.MINOR.PATCH``. In a nutshell, the version will be incremented
63
+ based on the following:
64
+
65
+ - ``MAJOR``: Incompatible or major changes.
66
+ - ``MINOR``: Backwards-compatible new features and enhancements.
67
+ - ``PATCH``: Backwards-compatible bugfixes and package updates.
68
+
69
+ ## Contributing
70
+
71
+ This is an active open-source project. We are always open to people who want to
72
+ use the code or contribute to it.
73
+
74
+ We've set up a separate document for our
75
+ [contribution guidelines](.github/CONTRIBUTING.md).
76
+
77
+ Thank you for being involved! :heart_eyes:
78
+
79
+ ## Setting up development environment
80
+
81
+ This Python project is fully managed using the [Poetry][poetry] dependency manager. But also relies on the use of NodeJS for certain checks during development.
82
+
83
+ You need at least:
84
+
85
+ - Python 3.11+
86
+ - [Poetry][poetry-install]
87
+ - NodeJS 12+ (including NPM)
88
+
89
+ To install all packages, including all development requirements:
90
+
91
+ ```bash
92
+ npm install
93
+ poetry install
94
+ ```
95
+
96
+ As this repository uses the [pre-commit][pre-commit] framework, all changes
97
+ are linted and tested with each commit. You can run all checks and tests
98
+ manually, using the following command:
99
+
100
+ ```bash
101
+ poetry run pre-commit run --all-files
102
+ ```
103
+
104
+ To run just the Python tests:
105
+
106
+ ```bash
107
+ poetry run pytest
108
+ ```
109
+
110
+ ## Authors & contributors
111
+
112
+ The content is by [Joost Lekkerkerker][joostlek].
113
+
114
+ For a full list of all authors and contributors,
115
+ check [the contributor's page][contributors].
116
+
117
+ ## License
118
+
119
+ MIT License
120
+
121
+ Copyright (c) 2024 Joost Lekkerkerker
122
+
123
+ Permission is hereby granted, free of charge, to any person obtaining a copy
124
+ of this software and associated documentation files (the "Software"), to deal
125
+ in the Software without restriction, including without limitation the rights
126
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
127
+ copies of the Software, and to permit persons to whom the Software is
128
+ furnished to do so, subject to the following conditions:
129
+
130
+ The above copyright notice and this permission notice shall be included in all
131
+ copies or substantial portions of the Software.
132
+
133
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
134
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
135
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
136
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
137
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
138
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
139
+ SOFTWARE.
140
+
141
+ [build-shield]: https://github.com/joostlek/python-nyt-games/actions/workflows/tests.yaml/badge.svg
142
+ [build]: https://github.com/joostlek/python-nyt-games/actions
143
+ [codecov-shield]: https://codecov.io/gh/joostlek/python-nyt-games/branch/master/graph/badge.svg
144
+ [codecov]: https://codecov.io/gh/joostlek/python-nyt-games
145
+ [commits-shield]: https://img.shields.io/github/commit-activity/y/joostlek/python-nyt-games.svg
146
+ [commits]: https://github.com/joostlek/python-nyt-games/commits/master
147
+ [contributors]: https://github.com/joostlek/python-nyt-games/graphs/contributors
148
+ [joostlek]: https://github.com/joostlek
149
+ [keepchangelog]: http://keepachangelog.com/en/1.0.0/
150
+ [license-shield]: https://img.shields.io/github/license/joostlek/python-nyt-games.svg
151
+ [maintenance-shield]: https://img.shields.io/maintenance/yes/2024.svg
152
+ [poetry-install]: https://python-poetry.org/docs/#installation
153
+ [poetry]: https://python-poetry.org
154
+ [pre-commit]: https://pre-commit.com/
155
+ [project-stage-shield]: https://img.shields.io/badge/project%20stage-stable-green.svg
156
+ [python-versions-shield]: https://img.shields.io/pypi/pyversions/nyt_games
157
+ [releases-shield]: https://img.shields.io/github/release/joostlek/python-nyt-games.svg
158
+ [releases]: https://github.com/joostlek/python-nyt-games/releases
159
+ [semver]: http://semver.org/spec/v2.0.0.html
160
+ [pypi]: https://pypi.org/project/nyt_games/
161
+
@@ -0,0 +1,129 @@
1
+ # Python: NYT Games
2
+
3
+ [![GitHub Release][releases-shield]][releases]
4
+ [![Python Versions][python-versions-shield]][pypi]
5
+ ![Project Stage][project-stage-shield]
6
+ ![Project Maintenance][maintenance-shield]
7
+ [![License][license-shield]](LICENSE.md)
8
+
9
+ [![Build Status][build-shield]][build]
10
+ [![Code Coverage][codecov-shield]][codecov]
11
+
12
+ Asynchronous Python client for NYT Games.
13
+
14
+ ## About
15
+
16
+ This package allows you to fetch data from NYT Games.
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ pip install nyt_games
22
+ ```
23
+
24
+ ## Changelog & Releases
25
+
26
+ This repository keeps a change log using [GitHub's releases][releases]
27
+ functionality. The format of the log is based on
28
+ [Keep a Changelog][keepchangelog].
29
+
30
+ Releases are based on [Semantic Versioning][semver], and use the format
31
+ of ``MAJOR.MINOR.PATCH``. In a nutshell, the version will be incremented
32
+ based on the following:
33
+
34
+ - ``MAJOR``: Incompatible or major changes.
35
+ - ``MINOR``: Backwards-compatible new features and enhancements.
36
+ - ``PATCH``: Backwards-compatible bugfixes and package updates.
37
+
38
+ ## Contributing
39
+
40
+ This is an active open-source project. We are always open to people who want to
41
+ use the code or contribute to it.
42
+
43
+ We've set up a separate document for our
44
+ [contribution guidelines](.github/CONTRIBUTING.md).
45
+
46
+ Thank you for being involved! :heart_eyes:
47
+
48
+ ## Setting up development environment
49
+
50
+ This Python project is fully managed using the [Poetry][poetry] dependency manager. But also relies on the use of NodeJS for certain checks during development.
51
+
52
+ You need at least:
53
+
54
+ - Python 3.11+
55
+ - [Poetry][poetry-install]
56
+ - NodeJS 12+ (including NPM)
57
+
58
+ To install all packages, including all development requirements:
59
+
60
+ ```bash
61
+ npm install
62
+ poetry install
63
+ ```
64
+
65
+ As this repository uses the [pre-commit][pre-commit] framework, all changes
66
+ are linted and tested with each commit. You can run all checks and tests
67
+ manually, using the following command:
68
+
69
+ ```bash
70
+ poetry run pre-commit run --all-files
71
+ ```
72
+
73
+ To run just the Python tests:
74
+
75
+ ```bash
76
+ poetry run pytest
77
+ ```
78
+
79
+ ## Authors & contributors
80
+
81
+ The content is by [Joost Lekkerkerker][joostlek].
82
+
83
+ For a full list of all authors and contributors,
84
+ check [the contributor's page][contributors].
85
+
86
+ ## License
87
+
88
+ MIT License
89
+
90
+ Copyright (c) 2024 Joost Lekkerkerker
91
+
92
+ Permission is hereby granted, free of charge, to any person obtaining a copy
93
+ of this software and associated documentation files (the "Software"), to deal
94
+ in the Software without restriction, including without limitation the rights
95
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
96
+ copies of the Software, and to permit persons to whom the Software is
97
+ furnished to do so, subject to the following conditions:
98
+
99
+ The above copyright notice and this permission notice shall be included in all
100
+ copies or substantial portions of the Software.
101
+
102
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
103
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
104
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
105
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
106
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
107
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
108
+ SOFTWARE.
109
+
110
+ [build-shield]: https://github.com/joostlek/python-nyt-games/actions/workflows/tests.yaml/badge.svg
111
+ [build]: https://github.com/joostlek/python-nyt-games/actions
112
+ [codecov-shield]: https://codecov.io/gh/joostlek/python-nyt-games/branch/master/graph/badge.svg
113
+ [codecov]: https://codecov.io/gh/joostlek/python-nyt-games
114
+ [commits-shield]: https://img.shields.io/github/commit-activity/y/joostlek/python-nyt-games.svg
115
+ [commits]: https://github.com/joostlek/python-nyt-games/commits/master
116
+ [contributors]: https://github.com/joostlek/python-nyt-games/graphs/contributors
117
+ [joostlek]: https://github.com/joostlek
118
+ [keepchangelog]: http://keepachangelog.com/en/1.0.0/
119
+ [license-shield]: https://img.shields.io/github/license/joostlek/python-nyt-games.svg
120
+ [maintenance-shield]: https://img.shields.io/maintenance/yes/2024.svg
121
+ [poetry-install]: https://python-poetry.org/docs/#installation
122
+ [poetry]: https://python-poetry.org
123
+ [pre-commit]: https://pre-commit.com/
124
+ [project-stage-shield]: https://img.shields.io/badge/project%20stage-stable-green.svg
125
+ [python-versions-shield]: https://img.shields.io/pypi/pyversions/nyt_games
126
+ [releases-shield]: https://img.shields.io/github/release/joostlek/python-nyt-games.svg
127
+ [releases]: https://github.com/joostlek/python-nyt-games/releases
128
+ [semver]: http://semver.org/spec/v2.0.0.html
129
+ [pypi]: https://pypi.org/project/nyt_games/
@@ -0,0 +1,162 @@
1
+ [tool.poetry]
2
+ name = "nyt_games"
3
+ version = "0.1.0"
4
+ description = "Asynchronous Python client for NYT games."
5
+ authors = ["Joost Lekkerkerker <joostlek@outlook.com>"]
6
+ maintainers = ["Joost Lekkerkerker <joostlek@outlook.com>"]
7
+ license = "MIT"
8
+ readme = "README.md"
9
+ homepage = "https://github.com/joostlek/python-nyt-games"
10
+ repository = "https://github.com/joostlek/python-nyt-games"
11
+ documentation = "https://github.com/joostlek/python-nyt-games"
12
+ keywords = ["NYT games", "api", "async", "client"]
13
+ classifiers = [
14
+ "Development Status :: 5 - Production/Stable",
15
+ "Framework :: AsyncIO",
16
+ "Intended Audience :: Developers",
17
+ "Natural Language :: English",
18
+ "Programming Language :: Python :: 3.11",
19
+ "Programming Language :: Python :: 3.12",
20
+ "Programming Language :: Python :: 3",
21
+ "Topic :: Software Development :: Libraries :: Python Modules",
22
+ ]
23
+ packages = [
24
+ { include = "nyt_games", from = "src" },
25
+ ]
26
+
27
+ [tool.poetry.dependencies]
28
+ python = "^3.11"
29
+ aiohttp = ">=3.0.0"
30
+ yarl = ">=1.6.0"
31
+ mashumaro = "^3.11"
32
+ orjson = ">=3.9.0"
33
+
34
+ [tool.poetry.group.dev.dependencies]
35
+ codespell = "2.3.0"
36
+ covdefaults = "2.3.0"
37
+ coverage = {version = "7.6.1", extras = ["toml"]}
38
+ mypy = "1.11.2"
39
+ pre-commit = "3.8.0"
40
+ pre-commit-hooks = "4.6.0"
41
+ pylint = "3.2.7"
42
+ pytest = "8.3.3"
43
+ pytest-asyncio = "0.24.0"
44
+ pytest-cov = "5.0.0"
45
+ ruff = "0.6.5"
46
+ safety = "3.2.7"
47
+ yamllint = "1.35.1"
48
+ syrupy = "4.7.1"
49
+ aioresponses = "0.7.6"
50
+
51
+ [tool.poetry.urls]
52
+ "Bug Tracker" = "https://github.com/joostlek/python-nyt-games/issues"
53
+ Changelog = "https://github.com/joostlek/python-nyt-games/releases"
54
+
55
+ [tool.coverage.report]
56
+ show_missing = true
57
+
58
+ [tool.coverage.run]
59
+ plugins = ["covdefaults"]
60
+ source = ["nyt_games"]
61
+
62
+ [tool.mypy]
63
+ # Specify the target platform details in config, so your developers are
64
+ # free to run mypy on Windows, Linux, or macOS and get consistent
65
+ # results.
66
+ platform = "linux"
67
+ python_version = "3.11"
68
+
69
+ # show error messages from unrelated files
70
+ follow_imports = "normal"
71
+
72
+ # suppress errors about unsatisfied imports
73
+ ignore_missing_imports = true
74
+
75
+ # be strict
76
+ check_untyped_defs = true
77
+ disallow_any_generics = true
78
+ disallow_incomplete_defs = true
79
+ disallow_subclassing_any = true
80
+ disallow_untyped_calls = true
81
+ disallow_untyped_decorators = true
82
+ disallow_untyped_defs = true
83
+ no_implicit_optional = true
84
+ strict_optional = true
85
+ warn_incomplete_stub = true
86
+ warn_no_return = true
87
+ warn_redundant_casts = true
88
+ warn_return_any = true
89
+ warn_unused_configs = true
90
+ warn_unused_ignores = true
91
+
92
+ [tool.pylint.MASTER]
93
+ ignore = [
94
+ "tests",
95
+ ]
96
+
97
+ [tool.pylint.BASIC]
98
+ good-names = [
99
+ "_",
100
+ "ex",
101
+ "fp",
102
+ "i",
103
+ "id",
104
+ "j",
105
+ "k",
106
+ "on",
107
+ "Run",
108
+ "T",
109
+ ]
110
+
111
+ [tool.pylint.DESIGN]
112
+ max-attributes = 8
113
+
114
+ [tool.pylint."MESSAGES CONTROL"]
115
+ disable = [
116
+ "duplicate-code",
117
+ "format",
118
+ "unsubscriptable-object",
119
+ "too-many-instance-attributes",
120
+ "wrong-import-order",
121
+ ]
122
+
123
+ [tool.pylint.SIMILARITIES]
124
+ ignore-imports = true
125
+
126
+ [tool.pylint.FORMAT]
127
+ max-line-length = 88
128
+
129
+ [tool.pytest.ini_options]
130
+ addopts = "--cov"
131
+ asyncio_mode = "auto"
132
+
133
+ [tool.ruff.lint]
134
+ ignore = [
135
+ "ANN101", # Self... explanatory
136
+ "ANN102", # cls... just as useless
137
+ "ANN401", # Opinioated warning on disallowing dynamically typed expressions
138
+ "COM812", # Conflicts with other rules
139
+ "D203", # Conflicts with other rules
140
+ "D213", # Conflicts with other rules
141
+ "D417", # False positives in some occasions
142
+ "ISC001", # Conflicts with other rules
143
+ "PLR2004", # Just annoying, not really useful
144
+ ]
145
+ select = ["ALL"]
146
+
147
+ [tool.ruff.lint.flake8-pytest-style]
148
+ fixture-parentheses = false
149
+ mark-parentheses = false
150
+
151
+ [tool.ruff.lint.isort]
152
+ known-first-party = ["nyt_games"]
153
+ force-sort-within-sections = true
154
+ split-on-trailing-comma = false
155
+ combine-as-imports = true
156
+
157
+ [tool.ruff.lint.mccabe]
158
+ max-complexity = 25
159
+
160
+ [build-system]
161
+ build-backend = "poetry.core.masonry.api"
162
+ requires = ["poetry-core>=1.0.0"]
@@ -0,0 +1,18 @@
1
+ """Asynchronous Python client for NYT Games."""
2
+
3
+ from nyt_games.exceptions import (
4
+ NYTGamesConnectionError,
5
+ NYTGamesError,
6
+ NYTGamesParseError,
7
+ )
8
+ from nyt_games.models import LatestDataStats, Wordle
9
+ from nyt_games.nyt_games import NYTGamesClient
10
+
11
+ __all__ = [
12
+ "NYTGamesClient",
13
+ "NYTGamesError",
14
+ "NYTGamesConnectionError",
15
+ "NYTGamesParseError",
16
+ "LatestDataStats",
17
+ "Wordle",
18
+ ]
@@ -0,0 +1,13 @@
1
+ """Asynchronous Python client for NYT Games."""
2
+
3
+
4
+ class NYTGamesError(Exception):
5
+ """Generic exception."""
6
+
7
+
8
+ class NYTGamesConnectionError(NYTGamesError):
9
+ """NYT Games connection exception."""
10
+
11
+
12
+ class NYTGamesParseError(NYTGamesError):
13
+ """NYT Games parse exception."""
@@ -0,0 +1,48 @@
1
+ """Models for NYT Games."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+ from datetime import date # noqa: TCH003
7
+ from typing import Any
8
+
9
+ from mashumaro import field_options
10
+ from mashumaro.mixins.orjson import DataClassORJSONMixin
11
+
12
+
13
+ @dataclass
14
+ class LatestData(DataClassORJSONMixin):
15
+ """LatestData model."""
16
+
17
+ player: LatestDataPlayer
18
+
19
+
20
+ @dataclass
21
+ class LatestDataPlayer(DataClassORJSONMixin):
22
+ """LatestData model."""
23
+
24
+ stats: LatestDataStats
25
+
26
+
27
+ @dataclass
28
+ class LatestDataStats(DataClassORJSONMixin):
29
+ """LatestData model."""
30
+
31
+ wordle: Wordle
32
+
33
+
34
+ @dataclass
35
+ class Wordle(DataClassORJSONMixin):
36
+ """Wordle model."""
37
+
38
+ games_played: int = field(metadata=field_options(alias="gamesPlayed"))
39
+ games_won: int = field(metadata=field_options(alias="gamesWon"))
40
+ guesses: dict[str, int]
41
+ current_streak: int = field(metadata=field_options(alias="currentStreak"))
42
+ max_streak: int = field(metadata=field_options(alias="maxStreak"))
43
+ last_won: date = field(metadata=field_options(alias="lastWonPrintDate"))
44
+
45
+ @classmethod
46
+ def __pre_deserialize__(cls, d: dict[str, dict[str, Any]]) -> dict[str, Any]:
47
+ """Pre deserialization hook."""
48
+ return d["calculatedStats"]
@@ -0,0 +1,108 @@
1
+ """Asynchronous Python client for NYT Games."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ from dataclasses import dataclass
7
+ from importlib import metadata
8
+ import socket
9
+ from typing import TYPE_CHECKING
10
+
11
+ from aiohttp import ClientError, ClientResponseError, ClientSession
12
+ from yarl import URL
13
+
14
+ from .exceptions import NYTGamesConnectionError
15
+ from .models import LatestData, LatestDataStats
16
+
17
+ if TYPE_CHECKING:
18
+ from typing_extensions import Self
19
+
20
+
21
+ VERSION = metadata.version(__package__)
22
+
23
+
24
+ @dataclass
25
+ class NYTGamesClient:
26
+ """Main class for handling connections with NYT Games."""
27
+
28
+ token: str
29
+ session: ClientSession | None = None
30
+ request_timeout: int = 10
31
+ _close_session: bool = False
32
+
33
+ async def _request(self, uri: str) -> str:
34
+ """Handle a request to NYT Games."""
35
+ url = URL.build(
36
+ scheme="https",
37
+ host="nytimes.com",
38
+ port=443,
39
+ ).joinpath(uri)
40
+
41
+ headers = {
42
+ "User-Agent": f"PythonNYTGames/{VERSION}",
43
+ "Accept": "application/json",
44
+ }
45
+
46
+ if self.session is None:
47
+ self.session = ClientSession()
48
+ self._close_session = True
49
+ self.session.cookie_jar.update_cookies({"NYT-S": self.token})
50
+
51
+ try:
52
+ async with asyncio.timeout(self.request_timeout):
53
+ response = await self.session.get(
54
+ url,
55
+ headers=headers,
56
+ )
57
+ except asyncio.TimeoutError as exception:
58
+ msg = "Timeout occurred while connecting to NYT Games"
59
+ raise NYTGamesConnectionError(msg) from exception
60
+ except (
61
+ ClientError,
62
+ ClientResponseError,
63
+ socket.gaierror,
64
+ ) as exception:
65
+ msg = "Error occurred while communicating with NYT Games"
66
+ raise NYTGamesConnectionError(msg) from exception
67
+
68
+ if response.status != 200:
69
+ content_type = response.headers.get("Content-Type", "")
70
+ text = await response.text()
71
+ msg = "Unexpected response from NYT Games"
72
+ raise NYTGamesConnectionError(
73
+ msg,
74
+ {"Content-Type": content_type, "response": text},
75
+ )
76
+
77
+ return await response.text()
78
+
79
+ async def get_latest_stats(self) -> LatestDataStats:
80
+ """Get latest stats."""
81
+ response = await self._request("svc/games/state/wordleV2/latests")
82
+ data = LatestData.from_json(response)
83
+ return data.player.stats
84
+
85
+ async def close(self) -> None:
86
+ """Close open client session."""
87
+ if self.session and self._close_session:
88
+ await self.session.close()
89
+
90
+ async def __aenter__(self) -> Self:
91
+ """Async enter.
92
+
93
+ Returns
94
+ -------
95
+ The NYTGamesClient object.
96
+
97
+ """
98
+ return self
99
+
100
+ async def __aexit__(self, *_exc_info: object) -> None:
101
+ """Async exit.
102
+
103
+ Args:
104
+ ----
105
+ _exc_info: Exec type.
106
+
107
+ """
108
+ await self.close()