django-esi 8.0.0b1__tar.gz → 8.0.0b2__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.

Potentially problematic release.


This version of django-esi might be problematic. Click here for more details.

Files changed (99) hide show
  1. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/PKG-INFO +3 -2
  2. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/__init__.py +1 -1
  3. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/aiopenapi3/plugins.py +12 -2
  4. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/clients.py +41 -1
  5. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/decorators.py +26 -10
  6. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/exceptions.py +7 -3
  7. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/helpers.py +1 -0
  8. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
  9. {django_esi-8.0.0b1/esi/locale/pl_PL → django_esi-8.0.0b2/esi/locale/cs_CZ}/LC_MESSAGES/django.po +2 -2
  10. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/de/LC_MESSAGES/django.mo +0 -0
  11. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/de/LC_MESSAGES/django.po +2 -2
  12. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/en/LC_MESSAGES/django.mo +0 -0
  13. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/en/LC_MESSAGES/django.po +2 -2
  14. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/es/LC_MESSAGES/django.mo +0 -0
  15. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/es/LC_MESSAGES/django.po +2 -2
  16. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/fr_FR/LC_MESSAGES/django.mo +0 -0
  17. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/fr_FR/LC_MESSAGES/django.po +2 -2
  18. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/it_IT/LC_MESSAGES/django.mo +0 -0
  19. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/it_IT/LC_MESSAGES/django.po +2 -2
  20. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/ja/LC_MESSAGES/django.mo +0 -0
  21. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/ja/LC_MESSAGES/django.po +2 -2
  22. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/ko_KR/LC_MESSAGES/django.mo +0 -0
  23. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/ko_KR/LC_MESSAGES/django.po +2 -2
  24. {django_esi-8.0.0b1/esi/locale/pl_PL → django_esi-8.0.0b2/esi/locale/nl_NL}/LC_MESSAGES/django.mo +0 -0
  25. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/nl_NL/LC_MESSAGES/django.po +2 -2
  26. {django_esi-8.0.0b1/esi/locale/nl_NL → django_esi-8.0.0b2/esi/locale/pl_PL}/LC_MESSAGES/django.mo +0 -0
  27. {django_esi-8.0.0b1/esi/locale/cs_CZ → django_esi-8.0.0b2/esi/locale/pl_PL}/LC_MESSAGES/django.po +2 -2
  28. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/ru/LC_MESSAGES/django.mo +0 -0
  29. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/ru/LC_MESSAGES/django.po +2 -2
  30. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/sk/LC_MESSAGES/django.mo +0 -0
  31. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/sk/LC_MESSAGES/django.po +2 -2
  32. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/uk/LC_MESSAGES/django.mo +0 -0
  33. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/uk/LC_MESSAGES/django.po +2 -2
  34. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/zh_Hans/LC_MESSAGES/django.mo +0 -0
  35. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/locale/zh_Hans/LC_MESSAGES/django.po +2 -2
  36. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/managers.pyi +3 -0
  37. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/openapi_clients.py +139 -31
  38. django_esi-8.0.0b2/esi/rate_limiting.py +107 -0
  39. django_esi-8.0.0b2/esi/signals.py +21 -0
  40. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/tests/__init__.py +30 -8
  41. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/tests/test_decorators.py +61 -1
  42. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/tests/test_openapi.json +65 -2
  43. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/tests/test_openapi.py +387 -47
  44. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/pyproject.toml +2 -1
  45. django_esi-8.0.0b1/esi/rate_limiting.py +0 -78
  46. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/LICENSE +0 -0
  47. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/README.md +0 -0
  48. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/admin.py +0 -0
  49. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/app_settings.py +0 -0
  50. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/apps.py +0 -0
  51. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/checks.py +0 -0
  52. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/errors.py +0 -0
  53. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/management/commands/__init__.py +0 -0
  54. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/management/commands/generate_esi_stubs.py +0 -0
  55. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/management/commands/migrate_to_ssov2.py +0 -0
  56. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/managers.py +0 -0
  57. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/migrations/0001_initial.py +0 -0
  58. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/migrations/0002_scopes_20161208.py +0 -0
  59. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/migrations/0003_hide_tokens_from_admin_site.py +0 -0
  60. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/migrations/0004_remove_unique_access_token.py +0 -0
  61. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/migrations/0005_remove_token_length_limit.py +0 -0
  62. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/migrations/0006_remove_url_length_limit.py +0 -0
  63. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/migrations/0007_fix_mysql_8_migration.py +0 -0
  64. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/migrations/0008_nullable_refresh_token.py +0 -0
  65. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/migrations/0009_set_old_tokens_to_sso_v1.py +0 -0
  66. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/migrations/0010_set_new_tokens_to_sso_v2.py +0 -0
  67. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/migrations/0011_add_token_indices.py +0 -0
  68. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/migrations/0012_fix_token_type_choices.py +0 -0
  69. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/migrations/0013_squashed_0012_fix_token_type_choices.py +0 -0
  70. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/migrations/__init__.py +0 -0
  71. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/models.py +0 -0
  72. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/static/esi/img/EVE_SSO_Login_Buttons_Large_Black.png +0 -0
  73. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/static/esi/img/EVE_SSO_Login_Buttons_Large_White.png +0 -0
  74. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/static/esi/img/EVE_SSO_Login_Buttons_Small_Black.png +0 -0
  75. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/static/esi/img/EVE_SSO_Login_Buttons_Small_White.png +0 -0
  76. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/stubs.py +0 -0
  77. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/stubs.pyi +0 -0
  78. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/tasks.py +0 -0
  79. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/templates/esi/select_token.html +0 -0
  80. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/templatetags/__init__.py +0 -0
  81. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/templatetags/scope_tags.py +0 -0
  82. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/tests/client_authed_pilot.py +0 -0
  83. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/tests/client_public_pilot.py +0 -0
  84. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/tests/factories.py +0 -0
  85. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/tests/factories_2.py +0 -0
  86. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/tests/jwt_factory.py +0 -0
  87. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/tests/test_checks.py +0 -0
  88. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/tests/test_clients.py +0 -0
  89. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/tests/test_management_command.py +0 -0
  90. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/tests/test_managers.py +0 -0
  91. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/tests/test_models.py +0 -0
  92. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/tests/test_swagger.json +0 -0
  93. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/tests/test_swagger_full.json +0 -0
  94. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/tests/test_tasks.py +0 -0
  95. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/tests/test_templatetags.py +0 -0
  96. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/tests/test_views.py +0 -0
  97. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/tests/threading_pilot.py +0 -0
  98. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/urls.py +0 -0
  99. {django_esi-8.0.0b1 → django_esi-8.0.0b2}/esi/views.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-esi
3
- Version: 8.0.0b1
3
+ Version: 8.0.0b2
4
4
  Summary: Django app for accessing the EVE Swagger Interface (ESI).
5
5
  Keywords: eveonline
6
6
  Author-email: Alliance Auth <adarnof@gmail.com>
@@ -9,7 +9,6 @@ Description-Content-Type: text/markdown
9
9
  Classifier: Environment :: Web Environment
10
10
  Classifier: Framework :: Django
11
11
  Classifier: Framework :: Django :: 4.2
12
- Classifier: Framework :: Django :: 5.1
13
12
  Classifier: Framework :: Django :: 5.2
14
13
  Classifier: Intended Audience :: Developers
15
14
  Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
@@ -28,8 +27,10 @@ Requires-Dist: aiopenapi3
28
27
  Requires-Dist: bravado>=10.6,<12
29
28
  Requires-Dist: celery>=4.0.2
30
29
  Requires-Dist: django>=4.2,<6
30
+ Requires-Dist: django-redis>=5.2
31
31
  Requires-Dist: httpx[brotli, http2, zstd]
32
32
  Requires-Dist: jsonschema<4
33
+ Requires-Dist: pydantic>=2.12.3
33
34
  Requires-Dist: python-jose>=3.3
34
35
  Requires-Dist: requests>=2.26
35
36
  Requires-Dist: requests-oauthlib>=0.8
@@ -1,6 +1,6 @@
1
1
  """Django app for accessing the EVE Swagger Interface (ESI)."""
2
2
 
3
- __version__ = "8.0.0-beta.1"
3
+ __version__ = "8.0.0-beta.2"
4
4
  __title__ = 'Django-ESI'
5
5
  __url__ = 'https://gitlab.com/allianceauth/django-esi'
6
6
  __build_date__ = "2025-09-18"
@@ -1,6 +1,9 @@
1
1
  import logging
2
2
  from typing import Any
3
+
3
4
  from collections.abc import Generator
5
+ from django.conf import settings
6
+
4
7
  from aiopenapi3.plugin import Document, Init
5
8
 
6
9
  logger = logging.getLogger(__name__)
@@ -54,9 +57,16 @@ class MinifySpec(Document):
54
57
  self.keep_ops = operations
55
58
 
56
59
  def parsed(self, ctx: Document.Context) -> Document.Context:
57
- if self.keep_tags == set() and self.keep_ops == []:
58
- logger.error("No tag/path filtering supplied to ESI Client. Using all tags. This will bloat memory use!")
60
+
61
+ if len(self.keep_tags) == 0 and self.keep_ops == []:
62
+ logger.error("No tag/path filtering supplied to ESI Client. Using all tags. This throw an error with `DEBUG=False`!", stack_info=True)
63
+ if not getattr(settings, "DEBUG", False):
64
+ # we are in production mode throw error to protect RAM.
65
+ raise AttributeError("No tag/path filtering supplied to ESI Client.")
66
+ # We are in debug mode allow an unfiltered client.
59
67
  return ctx
68
+
69
+ # filter the client.
60
70
  spec = ctx.document
61
71
 
62
72
  remove_paths = set()
@@ -1,5 +1,6 @@
1
1
  import json
2
2
  import logging
3
+ from timeit import default_timer
3
4
  import warnings
4
5
  import datetime as dt
5
6
  from hashlib import md5
@@ -10,7 +11,7 @@ from urllib import parse as urlparse
10
11
  from bravado import requests_client
11
12
  from bravado.client import SwaggerClient
12
13
  from bravado.exception import (
13
- HTTPBadGateway, HTTPGatewayTimeout, HTTPServiceUnavailable,
14
+ HTTPBadGateway, HTTPGatewayTimeout, HTTPServiceUnavailable, HTTPError,
14
15
  )
15
16
  from bravado.http_future import HttpFuture
16
17
  from bravado.swagger_model import Loader
@@ -22,6 +23,7 @@ from django.core.cache import cache
22
23
 
23
24
  from . import __title__, __url__, __version__, app_settings
24
25
  from .errors import TokenExpiredError
26
+ from .signals import esi_request_statistics
25
27
 
26
28
  logger = logging.getLogger(__name__)
27
29
 
@@ -144,6 +146,19 @@ class CachingHttpFuture(HttpFuture):
144
146
  for language in my_languages
145
147
  }
146
148
 
149
+ def _send_signal(self, status_code: int, headers: dict = {}, latency: float = 0) -> None:
150
+ """
151
+ Dispatch the esi request statistics signal
152
+ """
153
+ esi_request_statistics.send(
154
+ sender=self.__class__,
155
+ operation=self.operation.path_name,
156
+ status_code=status_code,
157
+ headers=headers,
158
+ latency=latency,
159
+ bucket=""
160
+ )
161
+
147
162
  def result(self, **kwargs) -> Any | tuple[Any, IncomingResponse]:
148
163
  """Executes the request and returns the response from ESI. Response will
149
164
  include the requested / first page only if there are more pages available.
@@ -191,6 +206,9 @@ class CachingHttpFuture(HttpFuture):
191
206
  )
192
207
 
193
208
  if cached:
209
+ self._send_signal(
210
+ status_code=0
211
+ )
194
212
  result, response = cached
195
213
  expiry = self._time_to_expiry(str(response.headers.get('Expires')))
196
214
  if expiry < 0:
@@ -245,6 +263,7 @@ class CachingHttpFuture(HttpFuture):
245
263
 
246
264
  retries = 0
247
265
  while retries <= max_retries:
266
+ _t = default_timer()
248
267
  try:
249
268
  if app_settings.ESI_INFO_LOGGING_ENABLED:
250
269
  params = self.future.request.params
@@ -269,6 +288,11 @@ class CachingHttpFuture(HttpFuture):
269
288
  logger.debug('ESI response content: %s', response.text)
270
289
  break
271
290
  except (HTTPBadGateway, HTTPGatewayTimeout, HTTPServiceUnavailable) as ex:
291
+ self._send_signal(
292
+ status_code=ex.status_code,
293
+ headers=ex.response.headers,
294
+ latency=default_timer() - _t
295
+ )
272
296
  if retries < max_retries:
273
297
  retries += 1
274
298
  logger.warning(
@@ -285,7 +309,23 @@ class CachingHttpFuture(HttpFuture):
285
309
  sleep(wait_secs)
286
310
  else:
287
311
  raise ex
312
+ except HTTPError as ex:
313
+ """
314
+ Throw any other error into the signal
315
+ then just re-raise
316
+ """
317
+ self._send_signal(
318
+ status_code=ex.status_code,
319
+ headers=ex.response.headers,
320
+ latency=default_timer() - _t
321
+ )
322
+ raise ex
288
323
 
324
+ self._send_signal(
325
+ status_code=response.status_code,
326
+ headers=response.headers,
327
+ latency=default_timer() - _t
328
+ )
289
329
  # restore original value
290
330
  self.request_config.also_return_response = _also_return_response
291
331
  return result, response
@@ -1,7 +1,8 @@
1
- import functools
2
1
  import logging
3
2
  import time
4
3
  from functools import wraps
4
+ from typing import Any
5
+ from collections.abc import Callable
5
6
 
6
7
  from django.core.cache import cache
7
8
 
@@ -227,12 +228,20 @@ def single_use_token(scopes='', new=False):
227
228
  return decorator
228
229
 
229
230
 
230
- def wait_for_esi_errorlimit_reset(cache_key="esi_error_limit_reset", poll_interval=1):
231
+ def wait_for_esi_errorlimit_reset(cache_key="esi_error_limit_reset", poll_interval=1) -> Callable[..., Callable[..., Any]]:
232
+ """
233
+ Decorator to apply a polling sleep while the ESI Server/Client is in an Error Limit state
234
+ The preferred non-blocking method is to retry your tasks after the limit reset time has passed
235
+
236
+ Args:
237
+ cache_key (str, optional): NOT USUALLY CHANGED. Defaults to "esi_error_limit_reset".
238
+ poll_interval (int, optional): Interval in seconds to poll redis. Defaults to 1.
239
+ """
231
240
  def decorator(func):
232
241
  def wrapper(*args, **kwargs):
233
242
  reset = cache.get(cache_key)
234
243
  if reset is not None:
235
- print(f"ESI Error Limited, waiting {reset}s before retrying...")
244
+ logger.error(f"ESI Error Limited, waiting {reset}s before retrying...")
236
245
  while cache.get(cache_key):
237
246
  time.sleep(poll_interval)
238
247
  return func(*args, **kwargs)
@@ -240,16 +249,23 @@ def wait_for_esi_errorlimit_reset(cache_key="esi_error_limit_reset", poll_interv
240
249
  return decorator
241
250
 
242
251
 
243
- def esi_rate_limiter_bucketed(
244
- bucket: ESIRateLimitBucket,
245
- raise_on_limit: bool = True,
246
- ):
247
- # TODO Investigate esi cache hits.
252
+ def esi_rate_limiter_bucketed(bucket: ESIRateLimitBucket, raise_on_limit: bool = True):
253
+ """
254
+ Decorator for custom manual rate limits on some endpoints to apply a polling sleep while the bucket is exhausted.
255
+ MARKET_DATA_HISTORY
256
+ CHARACTER_CORPORATION_HISTORY
257
+ The preferred non-blocking method is to retry your tasks after the limit reset time has passed
258
+
248
259
 
260
+ Args:
261
+ bucket (ESIRateLimitBucket): The Bucket to rate limit against
262
+ raise_on_limit (bool, optional): Whether to raise an Exception when the limit is reached. Defaults to True.
263
+ """
264
+ # TODO Investigate esi cache hits.
249
265
  def decorator(func):
250
- @functools.wraps(func)
266
+ @wraps(func)
251
267
  def wrapper(*args, **kwargs):
252
- ESIRateLimits.check_bucket(bucket, raise_on_limit)
268
+ ESIRateLimits.check_decr_bucket(bucket, raise_on_limit)
253
269
  return func(*args, **kwargs)
254
270
  return wrapper
255
271
  return decorator
@@ -4,10 +4,12 @@ from aiopenapi3.errors import HTTPServerError as base_HTTPServerError
4
4
  from aiopenapi3.errors import HTTPClientError as base_HTTPClientError
5
5
  from aiopenapi3.errors import HTTPError
6
6
 
7
+
7
8
  class ESIErrorLimitException(Exception):
8
9
  """ESI Global Error Limit Exceeded
9
10
  https://developers.eveonline.com/docs/services/esi/best-practices/#error-limit
10
11
  """
12
+
11
13
  def __init__(self, reset=None, *args, **kwargs) -> None:
12
14
  self.reset = reset
13
15
  msg = kwargs.get("message") or (
@@ -18,8 +20,10 @@ class ESIErrorLimitException(Exception):
18
20
 
19
21
  class ESIBucketLimitException(Exception):
20
22
  """Endpoint (Bucket) Specific Rate Limit Exceeded"""
21
- def __init__(self, bucket, *args, **kwargs) -> None:
23
+
24
+ def __init__(self, bucket, reset: float = 0, *args, **kwargs) -> None:
22
25
  self.bucket = bucket
26
+ self.reset = reset
23
27
  msg = kwargs.get("message") or f"ESI bucket limit reached for {bucket}."
24
28
  super().__init__(msg, *args)
25
29
 
@@ -37,11 +41,11 @@ class HTTPNotModified(HTTPError):
37
41
 
38
42
  @dataclasses.dataclass(repr=False)
39
43
  class HTTPClientError(base_HTTPClientError):
40
- """response code 4xx"""
44
+ """HTTP Response Code 4xx"""
41
45
  pass
42
46
 
43
47
 
44
48
  @dataclasses.dataclass(repr=False)
45
49
  class HTTPServerError(base_HTTPServerError):
46
- """response code 5xx"""
50
+ """HTTP Response Code 5xx"""
47
51
  pass
@@ -25,6 +25,7 @@ def get_token(character_id: int, scopes: list) -> Token:
25
25
  )
26
26
  return token
27
27
 
28
+
28
29
  def pascal_case_string(string: str) -> str:
29
30
  """
30
31
  Convert a string to PascalCase by capitalizing the first letter of each word and removing spaces,
@@ -6,9 +6,9 @@
6
6
  #, fuzzy
7
7
  msgid ""
8
8
  msgstr ""
9
- "Project-Id-Version: Django ESI 8.0.0-beta.1\n"
9
+ "Project-Id-Version: Django ESI 8.0.0-beta.2\n"
10
10
  "Report-Msgid-Bugs-To: https://gitlab.com/allianceauth/django-esi/-/issues\n"
11
- "POT-Creation-Date: 2025-10-17 15:19+1000\n"
11
+ "POT-Creation-Date: 2025-10-31 15:18+1000\n"
12
12
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -9,9 +9,9 @@
9
9
  #, fuzzy
10
10
  msgid ""
11
11
  msgstr ""
12
- "Project-Id-Version: Django ESI 8.0.0-beta.1\n"
12
+ "Project-Id-Version: Django ESI 8.0.0-beta.2\n"
13
13
  "Report-Msgid-Bugs-To: https://gitlab.com/allianceauth/django-esi/-/issues\n"
14
- "POT-Creation-Date: 2025-10-17 15:19+1000\n"
14
+ "POT-Creation-Date: 2025-10-31 15:18+1000\n"
15
15
  "PO-Revision-Date: 2023-10-25 11:04+0000\n"
16
16
  "Last-Translator: Peter Pfeufer, 2023\n"
17
17
  "Language-Team: German (https://app.transifex.com/alliance-auth/teams/107430/"
@@ -6,9 +6,9 @@
6
6
  #, fuzzy
7
7
  msgid ""
8
8
  msgstr ""
9
- "Project-Id-Version: Django ESI 8.0.0-beta.1\n"
9
+ "Project-Id-Version: Django ESI 8.0.0-beta.2\n"
10
10
  "Report-Msgid-Bugs-To: https://gitlab.com/allianceauth/django-esi/-/issues\n"
11
- "POT-Creation-Date: 2025-10-17 15:19+1000\n"
11
+ "POT-Creation-Date: 2025-10-31 15:18+1000\n"
12
12
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -9,9 +9,9 @@
9
9
  #, fuzzy
10
10
  msgid ""
11
11
  msgstr ""
12
- "Project-Id-Version: Django ESI 8.0.0-beta.1\n"
12
+ "Project-Id-Version: Django ESI 8.0.0-beta.2\n"
13
13
  "Report-Msgid-Bugs-To: https://gitlab.com/allianceauth/django-esi/-/issues\n"
14
- "POT-Creation-Date: 2025-10-17 15:19+1000\n"
14
+ "POT-Creation-Date: 2025-10-31 15:18+1000\n"
15
15
  "PO-Revision-Date: 2023-10-25 11:04+0000\n"
16
16
  "Last-Translator: trenus, 2023\n"
17
17
  "Language-Team: Spanish (https://app.transifex.com/alliance-auth/teams/107430/"
@@ -9,9 +9,9 @@
9
9
  #, fuzzy
10
10
  msgid ""
11
11
  msgstr ""
12
- "Project-Id-Version: Django ESI 8.0.0-beta.1\n"
12
+ "Project-Id-Version: Django ESI 8.0.0-beta.2\n"
13
13
  "Report-Msgid-Bugs-To: https://gitlab.com/allianceauth/django-esi/-/issues\n"
14
- "POT-Creation-Date: 2025-10-17 15:19+1000\n"
14
+ "POT-Creation-Date: 2025-10-31 15:18+1000\n"
15
15
  "PO-Revision-Date: 2020-12-28 06:44+0000\n"
16
16
  "Last-Translator: rockclodbuster, 2023\n"
17
17
  "Language-Team: French (France) (https://app.transifex.com/alliance-auth/"
@@ -9,9 +9,9 @@
9
9
  #, fuzzy
10
10
  msgid ""
11
11
  msgstr ""
12
- "Project-Id-Version: Django ESI 8.0.0-beta.1\n"
12
+ "Project-Id-Version: Django ESI 8.0.0-beta.2\n"
13
13
  "Report-Msgid-Bugs-To: https://gitlab.com/allianceauth/django-esi/-/issues\n"
14
- "POT-Creation-Date: 2025-10-17 15:19+1000\n"
14
+ "POT-Creation-Date: 2025-10-31 15:18+1000\n"
15
15
  "PO-Revision-Date: 2023-10-25 11:04+0000\n"
16
16
  "Last-Translator: Thomas Turini, 2024\n"
17
17
  "Language-Team: Italian (Italy) (https://app.transifex.com/alliance-auth/"
@@ -9,9 +9,9 @@
9
9
  #, fuzzy
10
10
  msgid ""
11
11
  msgstr ""
12
- "Project-Id-Version: Django ESI 8.0.0-beta.1\n"
12
+ "Project-Id-Version: Django ESI 8.0.0-beta.2\n"
13
13
  "Report-Msgid-Bugs-To: https://gitlab.com/allianceauth/django-esi/-/issues\n"
14
- "POT-Creation-Date: 2025-10-17 15:19+1000\n"
14
+ "POT-Creation-Date: 2025-10-31 15:18+1000\n"
15
15
  "PO-Revision-Date: 2023-10-25 11:04+0000\n"
16
16
  "Last-Translator: kotaneko, 2023\n"
17
17
  "Language-Team: Japanese (https://app.transifex.com/alliance-auth/"
@@ -9,9 +9,9 @@
9
9
  #, fuzzy
10
10
  msgid ""
11
11
  msgstr ""
12
- "Project-Id-Version: Django ESI 8.0.0-beta.1\n"
12
+ "Project-Id-Version: Django ESI 8.0.0-beta.2\n"
13
13
  "Report-Msgid-Bugs-To: https://gitlab.com/allianceauth/django-esi/-/issues\n"
14
- "POT-Creation-Date: 2025-10-17 15:19+1000\n"
14
+ "POT-Creation-Date: 2025-10-31 15:18+1000\n"
15
15
  "PO-Revision-Date: 2023-10-25 11:04+0000\n"
16
16
  "Last-Translator: Seowon Jung <seowon@hawaii.edu>, 2023\n"
17
17
  "Language-Team: Korean (Korea) (https://app.transifex.com/alliance-auth/"
@@ -6,9 +6,9 @@
6
6
  #, fuzzy
7
7
  msgid ""
8
8
  msgstr ""
9
- "Project-Id-Version: Django ESI 8.0.0-beta.1\n"
9
+ "Project-Id-Version: Django ESI 8.0.0-beta.2\n"
10
10
  "Report-Msgid-Bugs-To: https://gitlab.com/allianceauth/django-esi/-/issues\n"
11
- "POT-Creation-Date: 2025-10-17 15:19+1000\n"
11
+ "POT-Creation-Date: 2025-10-31 15:18+1000\n"
12
12
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -6,9 +6,9 @@
6
6
  #, fuzzy
7
7
  msgid ""
8
8
  msgstr ""
9
- "Project-Id-Version: Django ESI 8.0.0-beta.1\n"
9
+ "Project-Id-Version: Django ESI 8.0.0-beta.2\n"
10
10
  "Report-Msgid-Bugs-To: https://gitlab.com/allianceauth/django-esi/-/issues\n"
11
- "POT-Creation-Date: 2025-10-17 15:19+1000\n"
11
+ "POT-Creation-Date: 2025-10-31 15:18+1000\n"
12
12
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -10,9 +10,9 @@
10
10
  #, fuzzy
11
11
  msgid ""
12
12
  msgstr ""
13
- "Project-Id-Version: Django ESI 8.0.0-beta.1\n"
13
+ "Project-Id-Version: Django ESI 8.0.0-beta.2\n"
14
14
  "Report-Msgid-Bugs-To: https://gitlab.com/allianceauth/django-esi/-/issues\n"
15
- "POT-Creation-Date: 2025-10-17 15:19+1000\n"
15
+ "POT-Creation-Date: 2025-10-31 15:18+1000\n"
16
16
  "PO-Revision-Date: 2023-10-25 11:04+0000\n"
17
17
  "Last-Translator: Gnevich <and.vareba81@gmail.com>, 2025\n"
18
18
  "Language-Team: Russian (https://app.transifex.com/alliance-auth/teams/107430/"
@@ -6,9 +6,9 @@
6
6
  #, fuzzy
7
7
  msgid ""
8
8
  msgstr ""
9
- "Project-Id-Version: Django ESI 8.0.0-beta.1\n"
9
+ "Project-Id-Version: Django ESI 8.0.0-beta.2\n"
10
10
  "Report-Msgid-Bugs-To: https://gitlab.com/allianceauth/django-esi/-/issues\n"
11
- "POT-Creation-Date: 2025-10-17 15:19+1000\n"
11
+ "POT-Creation-Date: 2025-10-31 15:18+1000\n"
12
12
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -6,9 +6,9 @@
6
6
  #, fuzzy
7
7
  msgid ""
8
8
  msgstr ""
9
- "Project-Id-Version: Django ESI 8.0.0-beta.1\n"
9
+ "Project-Id-Version: Django ESI 8.0.0-beta.2\n"
10
10
  "Report-Msgid-Bugs-To: https://gitlab.com/allianceauth/django-esi/-/issues\n"
11
- "POT-Creation-Date: 2025-10-17 15:19+1000\n"
11
+ "POT-Creation-Date: 2025-10-31 15:18+1000\n"
12
12
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -9,9 +9,9 @@
9
9
  #, fuzzy
10
10
  msgid ""
11
11
  msgstr ""
12
- "Project-Id-Version: Django ESI 8.0.0-beta.1\n"
12
+ "Project-Id-Version: Django ESI 8.0.0-beta.2\n"
13
13
  "Report-Msgid-Bugs-To: https://gitlab.com/allianceauth/django-esi/-/issues\n"
14
- "POT-Creation-Date: 2025-10-17 15:19+1000\n"
14
+ "POT-Creation-Date: 2025-10-31 15:18+1000\n"
15
15
  "PO-Revision-Date: 2023-10-25 11:04+0000\n"
16
16
  "Last-Translator: heguyChen, 2023\n"
17
17
  "Language-Team: Chinese Simplified (https://app.transifex.com/alliance-auth/"
@@ -54,6 +54,9 @@ class TokenManager(Manager[Token]):
54
54
  def get_queryset(self) -> "TokenQueryset":
55
55
  ...
56
56
 
57
+ def require_scopes(self, scope_string: str | list) -> "TokenQueryset":
58
+ ...
59
+
57
60
  def filter(self, *args: Any, **kwargs: Any) -> "TokenQueryset":
58
61
  ...
59
62