apitally 0.14.0rc1__tar.gz → 0.14.2__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.
Files changed (50) hide show
  1. {apitally-0.14.0rc1 → apitally-0.14.2}/.pre-commit-config.yaml +1 -1
  2. {apitally-0.14.0rc1 → apitally-0.14.2}/PKG-INFO +1 -1
  3. {apitally-0.14.0rc1 → apitally-0.14.2}/apitally/client/client_asyncio.py +14 -3
  4. {apitally-0.14.0rc1 → apitally-0.14.2}/apitally/client/client_threading.py +26 -4
  5. {apitally-0.14.0rc1 → apitally-0.14.2}/apitally/client/request_logging.py +24 -9
  6. {apitally-0.14.0rc1 → apitally-0.14.2}/apitally/django.py +4 -0
  7. {apitally-0.14.0rc1 → apitally-0.14.2}/apitally/flask.py +7 -1
  8. {apitally-0.14.0rc1 → apitally-0.14.2}/apitally/litestar.py +8 -1
  9. {apitally-0.14.0rc1 → apitally-0.14.2}/apitally/starlette.py +8 -2
  10. {apitally-0.14.0rc1 → apitally-0.14.2}/tests/test_client_request_logging.py +13 -8
  11. {apitally-0.14.0rc1 → apitally-0.14.2}/uv.lock +57 -60
  12. {apitally-0.14.0rc1 → apitally-0.14.2}/.github/workflows/publish.yaml +0 -0
  13. {apitally-0.14.0rc1 → apitally-0.14.2}/.github/workflows/summary.yaml +0 -0
  14. {apitally-0.14.0rc1 → apitally-0.14.2}/.github/workflows/tests.yaml +0 -0
  15. {apitally-0.14.0rc1 → apitally-0.14.2}/.gitignore +0 -0
  16. {apitally-0.14.0rc1 → apitally-0.14.2}/LICENSE +0 -0
  17. {apitally-0.14.0rc1 → apitally-0.14.2}/Makefile +0 -0
  18. {apitally-0.14.0rc1 → apitally-0.14.2}/README.md +0 -0
  19. {apitally-0.14.0rc1 → apitally-0.14.2}/apitally/__init__.py +0 -0
  20. {apitally-0.14.0rc1 → apitally-0.14.2}/apitally/client/__init__.py +0 -0
  21. {apitally-0.14.0rc1 → apitally-0.14.2}/apitally/client/client_base.py +0 -0
  22. {apitally-0.14.0rc1 → apitally-0.14.2}/apitally/client/consumers.py +0 -0
  23. {apitally-0.14.0rc1 → apitally-0.14.2}/apitally/client/logging.py +0 -0
  24. {apitally-0.14.0rc1 → apitally-0.14.2}/apitally/client/requests.py +0 -0
  25. {apitally-0.14.0rc1 → apitally-0.14.2}/apitally/client/server_errors.py +0 -0
  26. {apitally-0.14.0rc1 → apitally-0.14.2}/apitally/client/validation_errors.py +0 -0
  27. {apitally-0.14.0rc1 → apitally-0.14.2}/apitally/common.py +0 -0
  28. {apitally-0.14.0rc1 → apitally-0.14.2}/apitally/django_ninja.py +0 -0
  29. {apitally-0.14.0rc1 → apitally-0.14.2}/apitally/django_rest_framework.py +0 -0
  30. {apitally-0.14.0rc1 → apitally-0.14.2}/apitally/fastapi.py +0 -0
  31. {apitally-0.14.0rc1 → apitally-0.14.2}/apitally/py.typed +0 -0
  32. {apitally-0.14.0rc1 → apitally-0.14.2}/pyproject.toml +0 -0
  33. {apitally-0.14.0rc1 → apitally-0.14.2}/renovate.json +0 -0
  34. {apitally-0.14.0rc1 → apitally-0.14.2}/tests/__init__.py +0 -0
  35. {apitally-0.14.0rc1 → apitally-0.14.2}/tests/conftest.py +0 -0
  36. {apitally-0.14.0rc1 → apitally-0.14.2}/tests/constants.py +0 -0
  37. {apitally-0.14.0rc1 → apitally-0.14.2}/tests/django_ninja_urls.py +0 -0
  38. {apitally-0.14.0rc1 → apitally-0.14.2}/tests/django_rest_framework_urls.py +0 -0
  39. {apitally-0.14.0rc1 → apitally-0.14.2}/tests/test_client_asyncio.py +0 -0
  40. {apitally-0.14.0rc1 → apitally-0.14.2}/tests/test_client_consumers.py +0 -0
  41. {apitally-0.14.0rc1 → apitally-0.14.2}/tests/test_client_requests.py +0 -0
  42. {apitally-0.14.0rc1 → apitally-0.14.2}/tests/test_client_server_errors.py +0 -0
  43. {apitally-0.14.0rc1 → apitally-0.14.2}/tests/test_client_threading.py +0 -0
  44. {apitally-0.14.0rc1 → apitally-0.14.2}/tests/test_client_validation_errors.py +0 -0
  45. {apitally-0.14.0rc1 → apitally-0.14.2}/tests/test_django_ninja.py +0 -0
  46. {apitally-0.14.0rc1 → apitally-0.14.2}/tests/test_django_rest_framework.py +0 -0
  47. {apitally-0.14.0rc1 → apitally-0.14.2}/tests/test_fastapi.py +0 -0
  48. {apitally-0.14.0rc1 → apitally-0.14.2}/tests/test_flask.py +0 -0
  49. {apitally-0.14.0rc1 → apitally-0.14.2}/tests/test_litestar.py +0 -0
  50. {apitally-0.14.0rc1 → apitally-0.14.2}/tests/test_starlette.py +0 -0
@@ -8,7 +8,7 @@ repos:
8
8
  - id: trailing-whitespace
9
9
  - id: mixed-line-ending
10
10
  - repo: https://github.com/charliermarsh/ruff-pre-commit
11
- rev: v0.8.1
11
+ rev: v0.8.2
12
12
  hooks:
13
13
  - id: ruff
14
14
  args: ["--fix", "--exit-non-zero-on-fix"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: apitally
3
- Version: 0.14.0rc1
3
+ Version: 0.14.2
4
4
  Summary: Simple API monitoring & analytics for REST APIs built with FastAPI, Flask, Django, Starlette and Litestar.
5
5
  Project-URL: Homepage, https://apitally.io
6
6
  Project-URL: Documentation, https://docs.apitally.io
@@ -6,7 +6,7 @@ import random
6
6
  import time
7
7
  from contextlib import suppress
8
8
  from functools import partial
9
- from typing import Any, AsyncIterator, Dict, Optional, Tuple
9
+ from typing import Any, AsyncIterator, Dict, Optional, Tuple, Union
10
10
  from uuid import UUID
11
11
 
12
12
  import backoff
@@ -29,15 +29,26 @@ retry = partial(
29
29
 
30
30
 
31
31
  class ApitallyClient(ApitallyClientBase):
32
- def __init__(self, client_id: str, env: str, request_logging_config: Optional[RequestLoggingConfig] = None) -> None:
32
+ def __init__(
33
+ self,
34
+ client_id: str,
35
+ env: str,
36
+ request_logging_config: Optional[RequestLoggingConfig] = None,
37
+ proxy: Optional[Union[str, httpx.Proxy]] = None,
38
+ ) -> None:
33
39
  super().__init__(client_id=client_id, env=env, request_logging_config=request_logging_config)
40
+ self.proxy = proxy
34
41
  self._stop_sync_loop = False
35
42
  self._sync_loop_task: Optional[asyncio.Task] = None
36
43
  self._sync_data_queue: asyncio.Queue[Tuple[float, Dict[str, Any]]] = asyncio.Queue()
37
44
  self._set_startup_data_task: Optional[asyncio.Task] = None
38
45
 
39
46
  def get_http_client(self) -> httpx.AsyncClient:
40
- return httpx.AsyncClient(base_url=self.hub_url, timeout=REQUEST_TIMEOUT)
47
+ if httpx.__version__ >= "0.26.0":
48
+ # `proxy` parameter was added in version 0.26.0
49
+ return httpx.AsyncClient(base_url=self.hub_url, timeout=REQUEST_TIMEOUT, proxy=self.proxy)
50
+ else:
51
+ return httpx.AsyncClient(base_url=self.hub_url, timeout=REQUEST_TIMEOUT, proxies=self.proxy)
41
52
 
42
53
  def start_sync_loop(self) -> None:
43
54
  self._stop_sync_loop = False
@@ -47,8 +47,15 @@ except NameError:
47
47
 
48
48
 
49
49
  class ApitallyClient(ApitallyClientBase):
50
- def __init__(self, client_id: str, env: str, request_logging_config: Optional[RequestLoggingConfig] = None) -> None:
50
+ def __init__(
51
+ self,
52
+ client_id: str,
53
+ env: str,
54
+ request_logging_config: Optional[RequestLoggingConfig] = None,
55
+ proxy: Optional[str] = None,
56
+ ) -> None:
51
57
  super().__init__(client_id=client_id, env=env, request_logging_config=request_logging_config)
58
+ self.proxies = {"https": proxy} if proxy else None
52
59
  self._thread: Optional[Thread] = None
53
60
  self._stop_sync_loop = Event()
54
61
  self._sync_data_queue: Queue[Tuple[float, Dict[str, Any]]] = Queue()
@@ -145,7 +152,12 @@ class ApitallyClient(ApitallyClientBase):
145
152
  @retry(raise_on_giveup=False)
146
153
  def _send_startup_data(self, session: requests.Session, data: Dict[str, Any]) -> None:
147
154
  logger.debug("Sending startup data to Apitally hub")
148
- response = session.post(url=f"{self.hub_url}/startup", json=data, timeout=REQUEST_TIMEOUT)
155
+ response = session.post(
156
+ url=f"{self.hub_url}/startup",
157
+ json=data,
158
+ timeout=REQUEST_TIMEOUT,
159
+ proxies=self.proxies,
160
+ )
149
161
  self._handle_hub_response(response)
150
162
  self._startup_data_sent = True
151
163
  self._startup_data = None
@@ -153,12 +165,22 @@ class ApitallyClient(ApitallyClientBase):
153
165
  @retry()
154
166
  def _send_sync_data(self, session: requests.Session, data: Dict[str, Any]) -> None:
155
167
  logger.debug("Synchronizing data with Apitally hub")
156
- response = session.post(url=f"{self.hub_url}/sync", json=data, timeout=REQUEST_TIMEOUT)
168
+ response = session.post(
169
+ url=f"{self.hub_url}/sync",
170
+ json=data,
171
+ timeout=REQUEST_TIMEOUT,
172
+ proxies=self.proxies,
173
+ )
157
174
  self._handle_hub_response(response)
158
175
 
159
176
  def _send_log_data(self, session: requests.Session, uuid: UUID, fp: BufferedReader) -> None:
160
177
  logger.debug("Streaming request log data to Apitally hub")
161
- response = session.post(url=f"{self.hub_url}/log?uuid={uuid}", data=fp, timeout=REQUEST_TIMEOUT)
178
+ response = session.post(
179
+ url=f"{self.hub_url}/log?uuid={uuid}",
180
+ data=fp,
181
+ timeout=REQUEST_TIMEOUT,
182
+ proxies=self.proxies,
183
+ )
162
184
  if response.status_code == 402 and "Retry-After" in response.headers:
163
185
  with suppress(ValueError):
164
186
  retry_after = int(response.headers["Retry-After"])
@@ -35,6 +35,12 @@ EXCLUDE_PATH_PATTERNS = [
35
35
  r"/ready$",
36
36
  r"/live$",
37
37
  ]
38
+ EXCLUDE_USER_AGENT_PATTERNS = [
39
+ r"health[_- ]?check",
40
+ r"microsoft-azure-application-lb",
41
+ r"googlehc",
42
+ r"kube-probe",
43
+ ]
38
44
  MASK_QUERY_PARAM_PATTERNS = [
39
45
  r"auth",
40
46
  r"api-?key",
@@ -99,8 +105,8 @@ class RequestLoggingConfig:
99
105
  log_response_body: bool = False
100
106
  mask_query_params: List[str] = field(default_factory=list)
101
107
  mask_headers: List[str] = field(default_factory=list)
102
- mask_request_body_callback: Optional[Callable[[str, str, bytes], Optional[bytes]]] = None
103
- mask_response_body_callback: Optional[Callable[[str, str, bytes], Optional[bytes]]] = None
108
+ mask_request_body_callback: Optional[Callable[[RequestDict], Optional[bytes]]] = None
109
+ mask_response_body_callback: Optional[Callable[[RequestDict, ResponseDict], Optional[bytes]]] = None
104
110
  exclude_paths: List[str] = field(default_factory=list)
105
111
  exclude_callback: Optional[Callable[[RequestDict, ResponseDict], bool]] = None
106
112
 
@@ -162,7 +168,12 @@ class RequestLogger:
162
168
  if not self.enabled or self.suspend_until is not None:
163
169
  return
164
170
  parsed_url = urlparse(request["url"])
165
- if self._should_exclude_path(request["path"] or parsed_url.path) or self._should_exclude(request, response):
171
+ user_agent = self._get_user_agent(request["headers"])
172
+ if (
173
+ self._should_exclude_path(request["path"] or parsed_url.path)
174
+ or self._should_exclude_user_agent(user_agent)
175
+ or self._should_exclude(request, response)
176
+ ):
166
177
  return
167
178
 
168
179
  query = self._mask_query_params(parsed_url.query) if self.config.log_query_params else ""
@@ -178,9 +189,7 @@ class RequestLogger:
178
189
  and request["body"] != BODY_TOO_LARGE
179
190
  ):
180
191
  try:
181
- request["body"] = self.config.mask_request_body_callback(
182
- request["method"], request["path"] or parsed_url.path, request["body"]
183
- )
192
+ request["body"] = self.config.mask_request_body_callback(request)
184
193
  except Exception: # pragma: no cover
185
194
  logger.exception("User-provided mask_request_body_callback function raised an exception")
186
195
  request["body"] = None
@@ -197,9 +206,7 @@ class RequestLogger:
197
206
  and response["body"] != BODY_TOO_LARGE
198
207
  ):
199
208
  try:
200
- response["body"] = self.config.mask_response_body_callback(
201
- request["method"], request["path"] or parsed_url.path, response["body"]
202
- )
209
+ response["body"] = self.config.mask_response_body_callback(request, response)
203
210
  except Exception: # pragma: no cover
204
211
  logger.exception("User-provided mask_response_body_callback function raised an exception")
205
212
  response["body"] = None
@@ -275,6 +282,10 @@ class RequestLogger:
275
282
  patterns = self.config.exclude_paths + EXCLUDE_PATH_PATTERNS
276
283
  return self._match_patterns(url_path, patterns)
277
284
 
285
+ @lru_cache(maxsize=1000)
286
+ def _should_exclude_user_agent(self, user_agent: Optional[str]) -> bool:
287
+ return self._match_patterns(user_agent, EXCLUDE_USER_AGENT_PATTERNS) if user_agent is not None else False
288
+
278
289
  def _mask_query_params(self, query: str) -> str:
279
290
  query_params = parse_qsl(query)
280
291
  masked_query_params = [(k, v if not self._should_mask_query_param(k) else MASKED) for k, v in query_params]
@@ -306,6 +317,10 @@ class RequestLogger:
306
317
  content_type = next((v for k, v in headers if k.lower() == "content-type"), None)
307
318
  return content_type is not None and any(content_type.startswith(t) for t in ALLOWED_CONTENT_TYPES)
308
319
 
320
+ @staticmethod
321
+ def _get_user_agent(headers: List[Tuple[str, str]]) -> Optional[str]:
322
+ return next((v for k, v in headers if k.lower() == "user-agent"), None)
323
+
309
324
 
310
325
  def _check_writable_fs() -> bool:
311
326
  try:
@@ -41,6 +41,7 @@ class ApitallyMiddlewareConfig:
41
41
  app_version: Optional[str]
42
42
  identify_consumer_callback: Optional[Callable[[HttpRequest], Union[str, ApitallyConsumer, None]]]
43
43
  urlconfs: List[Optional[str]]
44
+ proxy: Optional[str]
44
45
 
45
46
 
46
47
  class ApitallyMiddleware:
@@ -71,6 +72,7 @@ class ApitallyMiddleware:
71
72
  client_id=self.config.client_id,
72
73
  env=self.config.env,
73
74
  request_logging_config=self.config.request_logging_config,
75
+ proxy=self.config.proxy,
74
76
  )
75
77
  self.client.start_sync_loop()
76
78
  self.client.set_startup_data(
@@ -96,6 +98,7 @@ class ApitallyMiddleware:
96
98
  app_version: Optional[str] = None,
97
99
  identify_consumer_callback: Optional[str] = None,
98
100
  urlconf: Optional[Union[List[Optional[str]], str]] = None,
101
+ proxy: Optional[str] = None,
99
102
  ) -> None:
100
103
  cls.config = ApitallyMiddlewareConfig(
101
104
  client_id=client_id,
@@ -106,6 +109,7 @@ class ApitallyMiddleware:
106
109
  if identify_consumer_callback
107
110
  else None,
108
111
  urlconfs=[urlconf] if urlconf is None or isinstance(urlconf, str) else urlconf,
112
+ proxy=proxy,
109
113
  )
110
114
 
111
115
  def __call__(self, request: HttpRequest) -> HttpResponse:
@@ -39,11 +39,17 @@ class ApitallyMiddleware:
39
39
  request_logging_config: Optional[RequestLoggingConfig] = None,
40
40
  app_version: Optional[str] = None,
41
41
  openapi_url: Optional[str] = None,
42
+ proxy: Optional[str] = None,
42
43
  ) -> None:
43
44
  self.app = app
44
45
  self.wsgi_app = app.wsgi_app
45
46
  self.patch_handle_exception()
46
- self.client = ApitallyClient(client_id=client_id, env=env, request_logging_config=request_logging_config)
47
+ self.client = ApitallyClient(
48
+ client_id=client_id,
49
+ env=env,
50
+ request_logging_config=request_logging_config,
51
+ proxy=proxy,
52
+ )
47
53
  self.client.start_sync_loop()
48
54
  self.delayed_set_startup_data(app_version, openapi_url)
49
55
 
@@ -4,6 +4,7 @@ import time
4
4
  from typing import Callable, Dict, List, Optional, Union
5
5
  from warnings import warn
6
6
 
7
+ from httpx import Proxy
7
8
  from litestar.app import DEFAULT_OPENAPI_CONFIG, Litestar
8
9
  from litestar.config.app import AppConfig
9
10
  from litestar.connection import Request
@@ -35,8 +36,14 @@ class ApitallyPlugin(InitPluginProtocol):
35
36
  app_version: Optional[str] = None,
36
37
  filter_openapi_paths: bool = True,
37
38
  identify_consumer_callback: Optional[Callable[[Request], Union[str, ApitallyConsumer, None]]] = None,
39
+ proxy: Optional[Union[str, Proxy]] = None,
38
40
  ) -> None:
39
- self.client = ApitallyClient(client_id=client_id, env=env, request_logging_config=request_logging_config)
41
+ self.client = ApitallyClient(
42
+ client_id=client_id,
43
+ env=env,
44
+ request_logging_config=request_logging_config,
45
+ proxy=proxy,
46
+ )
40
47
  self.app_version = app_version
41
48
  self.filter_openapi_paths = filter_openapi_paths
42
49
  self.identify_consumer_callback = identify_consumer_callback
@@ -7,7 +7,7 @@ import time
7
7
  from typing import Any, Callable, Dict, List, Optional, Union
8
8
  from warnings import warn
9
9
 
10
- from httpx import HTTPStatusError
10
+ from httpx import HTTPStatusError, Proxy
11
11
  from starlette.datastructures import Headers
12
12
  from starlette.requests import Request
13
13
  from starlette.routing import BaseRoute, Match, Router
@@ -38,10 +38,16 @@ class ApitallyMiddleware:
38
38
  app_version: Optional[str] = None,
39
39
  openapi_url: Optional[str] = "/openapi.json",
40
40
  identify_consumer_callback: Optional[Callable[[Request], Union[str, ApitallyConsumer, None]]] = None,
41
+ proxy: Optional[Union[str, Proxy]] = None,
41
42
  ) -> None:
42
43
  self.app = app
43
44
  self.identify_consumer_callback = identify_consumer_callback
44
- self.client = ApitallyClient(client_id=client_id, env=env, request_logging_config=request_logging_config)
45
+ self.client = ApitallyClient(
46
+ client_id=client_id,
47
+ env=env,
48
+ request_logging_config=request_logging_config,
49
+ proxy=proxy,
50
+ )
45
51
  self.client.start_sync_loop()
46
52
  self._delayed_set_startup_data_task: Optional[asyncio.Task] = None
47
53
  self.delayed_set_startup_data(app_version, openapi_url)
@@ -137,25 +137,30 @@ def test_request_log_masking(request_logger: RequestLogger, request_dict: Reques
137
137
 
138
138
  MASKED_QUOTED = quote(MASKED)
139
139
 
140
- def callback(method: str, path: str, body: bytes) -> Optional[bytes]:
141
- if method == "GET" and path == "/test":
140
+ def mask_request_body_callback(request: RequestDict) -> Optional[bytes]:
141
+ if request["method"] == "GET" and request["path"] == "/test":
142
142
  return None
143
- return body
143
+ return request["body"]
144
+
145
+ def mask_response_body_callback(request: RequestDict, response: ResponseDict) -> Optional[bytes]:
146
+ if request["method"] == "GET" and request["path"] == "/test":
147
+ return None
148
+ return response["body"]
144
149
 
145
150
  request_logger.config.mask_headers = ["test"]
146
151
  request_logger.config.mask_query_params = ["test"]
147
- request_logger.config.mask_request_body_callback = callback
148
- request_logger.config.mask_response_body_callback = callback
152
+ request_logger.config.mask_request_body_callback = mask_request_body_callback
153
+ request_logger.config.mask_response_body_callback = mask_response_body_callback
149
154
  request_dict["url"] = "http://localhost/test?secret=123456&test=123456&other=abcdef"
150
- request_dict["headers"] += [("Authorization", "Bearer 123456"), ("Test-Header", "123456")]
155
+ request_dict["headers"] += [("Authorization", "Bearer 123456"), ("X-Test", "123456")]
151
156
  request_logger.log_request(request_dict, response_dict)
152
157
 
153
158
  item = json.loads(request_logger.write_deque[0])
154
159
  assert item["request"]["url"] == f"http://localhost/test?secret={MASKED_QUOTED}&test={MASKED_QUOTED}&other=abcdef"
155
160
  assert ["Authorization", "Bearer 123456"] not in item["request"]["headers"]
156
161
  assert ["Authorization", MASKED] in item["request"]["headers"]
157
- assert ["Test-Header", "123456"] not in item["request"]["headers"]
158
- assert ["Test-Header", MASKED] in item["request"]["headers"]
162
+ assert ["X-Test", "123456"] not in item["request"]["headers"]
163
+ assert ["X-Test", MASKED] in item["request"]["headers"]
159
164
  assert ["Accept", "text/plain"] in item["request"]["headers"]
160
165
  assert item["request"]["body"] == base64.b64encode(BODY_MASKED).decode()
161
166
  assert item["response"]["body"] == base64.b64encode(BODY_MASKED).decode()
@@ -35,7 +35,7 @@ wheels = [
35
35
 
36
36
  [[package]]
37
37
  name = "apitally"
38
- version = "0.13.1.dev11+geee5877"
38
+ version = "0.14.0rc2.dev2+g29e3d58"
39
39
  source = { editable = "." }
40
40
  dependencies = [
41
41
  { name = "backoff" },
@@ -88,7 +88,7 @@ dev = [
88
88
  ]
89
89
  test = [
90
90
  { name = "pytest", version = "7.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" },
91
- { name = "pytest", version = "8.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" },
91
+ { name = "pytest", version = "8.3.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" },
92
92
  { name = "pytest-asyncio" },
93
93
  { name = "pytest-cov", version = "5.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" },
94
94
  { name = "pytest-cov", version = "6.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" },
@@ -190,14 +190,11 @@ wheels = [
190
190
 
191
191
  [[package]]
192
192
  name = "asttokens"
193
- version = "2.4.1"
193
+ version = "3.0.0"
194
194
  source = { registry = "https://pypi.org/simple" }
195
- dependencies = [
196
- { name = "six" },
197
- ]
198
- sdist = { url = "https://files.pythonhosted.org/packages/45/1d/f03bcb60c4a3212e15f99a56085d93093a497718adf828d050b9d675da81/asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0", size = 62284 }
195
+ sdist = { url = "https://files.pythonhosted.org/packages/4a/e7/82da0a03e7ba5141f05cce0d302e6eed121ae055e0456ca228bf693984bc/asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7", size = 61978 }
199
196
  wheels = [
200
- { url = "https://files.pythonhosted.org/packages/45/86/4736ac618d82a20d87d2f92ae19441ebc7ac9e7a581d7e58bbe79233b24a/asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24", size = 27764 },
197
+ { url = "https://files.pythonhosted.org/packages/25/8a/c46dcc25341b5bce5472c718902eb3d38600a903b14fa6aeecef3f21a46f/asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2", size = 26918 },
201
198
  ]
202
199
 
203
200
  [[package]]
@@ -604,7 +601,7 @@ wheels = [
604
601
 
605
602
  [[package]]
606
603
  name = "django"
607
- version = "4.2.16"
604
+ version = "4.2.17"
608
605
  source = { registry = "https://pypi.org/simple" }
609
606
  dependencies = [
610
607
  { name = "asgiref" },
@@ -612,9 +609,9 @@ dependencies = [
612
609
  { name = "sqlparse" },
613
610
  { name = "tzdata", marker = "sys_platform == 'win32'" },
614
611
  ]
615
- sdist = { url = "https://files.pythonhosted.org/packages/65/d8/a607ee443b54a4db4ad28902328b906ae6218aa556fb9b3ac45c0bcb313d/Django-4.2.16.tar.gz", hash = "sha256:6f1616c2786c408ce86ab7e10f792b8f15742f7b7b7460243929cb371e7f1dad", size = 10436023 }
612
+ sdist = { url = "https://files.pythonhosted.org/packages/63/58/709978ddf7e9393c0a89b57a5edbd764ee76eeea68697af3f77f3820980b/Django-4.2.17.tar.gz", hash = "sha256:6b56d834cc94c8b21a8f4e775064896be3b4a4ca387f2612d4406a5927cd2fdc", size = 10437674 }
616
613
  wheels = [
617
- { url = "https://files.pythonhosted.org/packages/94/2c/6b6c7e493d5ea789416918658ebfa16be7a64c77610307497ed09a93c8c4/Django-4.2.16-py3-none-any.whl", hash = "sha256:1ddc333a16fc139fd253035a1606bb24261951bbc3a6ca256717fa06cc41a898", size = 7992936 },
614
+ { url = "https://files.pythonhosted.org/packages/5e/85/457360cb3de496382e35db4c2af054066df5c40e26df31400d0109a0500c/Django-4.2.17-py3-none-any.whl", hash = "sha256:3a93350214ba25f178d4045c0786c61573e7dbfa3c509b3551374f1e11ba8de0", size = 7993390 },
618
615
  ]
619
616
 
620
617
  [[package]]
@@ -700,16 +697,16 @@ wheels = [
700
697
 
701
698
  [[package]]
702
699
  name = "fastapi"
703
- version = "0.115.5"
700
+ version = "0.115.6"
704
701
  source = { registry = "https://pypi.org/simple" }
705
702
  dependencies = [
706
703
  { name = "pydantic" },
707
704
  { name = "starlette" },
708
705
  { name = "typing-extensions" },
709
706
  ]
710
- sdist = { url = "https://files.pythonhosted.org/packages/ae/29/f71316b9273b6552a263748e49cd7b83898dc9499a663d30c7b9cb853cb8/fastapi-0.115.5.tar.gz", hash = "sha256:0e7a4d0dc0d01c68df21887cce0945e72d3c48b9f4f79dfe7a7d53aa08fbb289", size = 301047 }
707
+ sdist = { url = "https://files.pythonhosted.org/packages/93/72/d83b98cd106541e8f5e5bfab8ef2974ab45a62e8a6c5b5e6940f26d2ed4b/fastapi-0.115.6.tar.gz", hash = "sha256:9ec46f7addc14ea472958a96aae5b5de65f39721a46aaf5705c480d9a8b76654", size = 301336 }
711
708
  wheels = [
712
- { url = "https://files.pythonhosted.org/packages/54/c4/148d5046a96c428464557264877ae5a9338a83bbe0df045088749ec89820/fastapi-0.115.5-py3-none-any.whl", hash = "sha256:596b95adbe1474da47049e802f9a65ab2ffa9c2b07e7efee70eb8a66c9f2f796", size = 94866 },
709
+ { url = "https://files.pythonhosted.org/packages/52/b3/7e4df40e585df024fac2f80d1a2d579c854ac37109675db2b0cc22c0bb9e/fastapi-0.115.6-py3-none-any.whl", hash = "sha256:e9240b29e36fa8f4bb7290316988e90c381e5092e0cbe84e7818cc3713bcf305", size = 94843 },
713
710
  ]
714
711
 
715
712
  [[package]]
@@ -1020,11 +1017,11 @@ wheels = [
1020
1017
 
1021
1018
  [[package]]
1022
1019
  name = "litestar-htmx"
1023
- version = "0.4.0"
1020
+ version = "0.4.1"
1024
1021
  source = { registry = "https://pypi.org/simple" }
1025
- sdist = { url = "https://files.pythonhosted.org/packages/ff/bc/68dda03c35e5067a09a4e57f9b5af958d0718da00ae741483d8d95a8fb5a/litestar_htmx-0.4.0.tar.gz", hash = "sha256:b5f53aa25b665d673fe2e9d835ff711f7fe28fa8f57b87b61e4f6317b983632e", size = 101616 }
1022
+ sdist = { url = "https://files.pythonhosted.org/packages/c9/0c/06ab03ee497d207dd8cb7588d1940be0b373a8ffdc7be3ec6d7e91c17ae2/litestar_htmx-0.4.1.tar.gz", hash = "sha256:ba2537008eb8cc18bfc8bee5cecb280924c7818bb1c066d79eae4b221696ca08", size = 101877 }
1026
1023
  wheels = [
1027
- { url = "https://files.pythonhosted.org/packages/b4/ea/e423f6dd967ae32157e2abc74bf4cd714adf94536ca9926358d4f59da175/litestar_htmx-0.4.0-py3-none-any.whl", hash = "sha256:81e784b91a5a5ca6061d86271e026de7d785d90a4367c6b9c8f0c724b26986c4", size = 9784 },
1024
+ { url = "https://files.pythonhosted.org/packages/9d/99/3ea64a79a2f4fea5225ccd0128201a3b8eab5e216b8fba8b778b8c462f29/litestar_htmx-0.4.1-py3-none-any.whl", hash = "sha256:ba2a8ff1e210f21980735b9cde13d239a2b7c3627cb4aeb425d66f4a314d1a59", size = 9970 },
1028
1025
  ]
1029
1026
 
1030
1027
  [[package]]
@@ -1499,16 +1496,16 @@ wheels = [
1499
1496
 
1500
1497
  [[package]]
1501
1498
  name = "pydantic"
1502
- version = "2.10.2"
1499
+ version = "2.10.3"
1503
1500
  source = { registry = "https://pypi.org/simple" }
1504
1501
  dependencies = [
1505
1502
  { name = "annotated-types" },
1506
1503
  { name = "pydantic-core" },
1507
1504
  { name = "typing-extensions" },
1508
1505
  ]
1509
- sdist = { url = "https://files.pythonhosted.org/packages/41/86/a03390cb12cf64e2a8df07c267f3eb8d5035e0f9a04bb20fb79403d2a00e/pydantic-2.10.2.tar.gz", hash = "sha256:2bc2d7f17232e0841cbba4641e65ba1eb6fafb3a08de3a091ff3ce14a197c4fa", size = 785401 }
1506
+ sdist = { url = "https://files.pythonhosted.org/packages/45/0f/27908242621b14e649a84e62b133de45f84c255eecb350ab02979844a788/pydantic-2.10.3.tar.gz", hash = "sha256:cb5ac360ce894ceacd69c403187900a02c4b20b693a9dd1d643e1effab9eadf9", size = 786486 }
1510
1507
  wheels = [
1511
- { url = "https://files.pythonhosted.org/packages/d5/74/da832196702d0c56eb86b75bfa346db9238617e29b0b7ee3b8b4eccfe654/pydantic-2.10.2-py3-none-any.whl", hash = "sha256:cfb96e45951117c3024e6b67b25cdc33a3cb7b2fa62e239f7af1378358a1d99e", size = 456364 },
1508
+ { url = "https://files.pythonhosted.org/packages/62/51/72c18c55cf2f46ff4f91ebcc8f75aa30f7305f3d726be3f4ebffb4ae972b/pydantic-2.10.3-py3-none-any.whl", hash = "sha256:be04d85bbc7b65651c5f8e6b9976ed9c6f41782a55524cef079a34a0bb82144d", size = 456997 },
1512
1509
  ]
1513
1510
 
1514
1511
  [[package]]
@@ -1652,7 +1649,7 @@ wheels = [
1652
1649
 
1653
1650
  [[package]]
1654
1651
  name = "pytest"
1655
- version = "8.3.3"
1652
+ version = "8.3.4"
1656
1653
  source = { registry = "https://pypi.org/simple" }
1657
1654
  resolution-markers = [
1658
1655
  "python_full_version == '3.9.*'",
@@ -1666,9 +1663,9 @@ dependencies = [
1666
1663
  { name = "pluggy", marker = "python_full_version >= '3.9'" },
1667
1664
  { name = "tomli", marker = "python_full_version >= '3.9' and python_full_version < '3.11'" },
1668
1665
  ]
1669
- sdist = { url = "https://files.pythonhosted.org/packages/8b/6c/62bbd536103af674e227c41a8f3dcd022d591f6eed5facb5a0f31ee33bbc/pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181", size = 1442487 }
1666
+ sdist = { url = "https://files.pythonhosted.org/packages/05/35/30e0d83068951d90a01852cb1cef56e5d8a09d20c7f511634cc2f7e0372a/pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761", size = 1445919 }
1670
1667
  wheels = [
1671
- { url = "https://files.pythonhosted.org/packages/6b/77/7440a06a8ead44c7757a64362dd22df5760f9b12dc5f11b6188cd2fc27a0/pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2", size = 342341 },
1668
+ { url = "https://files.pythonhosted.org/packages/11/92/76a1c94d3afee238333bc0a42b82935dd8f9cf8ce9e336ff87ee14d9e1cf/pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", size = 343083 },
1672
1669
  ]
1673
1670
 
1674
1671
  [[package]]
@@ -1677,7 +1674,7 @@ version = "0.21.2"
1677
1674
  source = { registry = "https://pypi.org/simple" }
1678
1675
  dependencies = [
1679
1676
  { name = "pytest", version = "7.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" },
1680
- { name = "pytest", version = "8.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" },
1677
+ { name = "pytest", version = "8.3.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" },
1681
1678
  ]
1682
1679
  sdist = { url = "https://files.pythonhosted.org/packages/ae/53/57663d99acaac2fcdafdc697e52a9b1b7d6fcf36616281ff9768a44e7ff3/pytest_asyncio-0.21.2.tar.gz", hash = "sha256:d67738fc232b94b326b9d060750beb16e0074210b98dd8b58a5239fa2a154f45", size = 30656 }
1683
1680
  wheels = [
@@ -1710,7 +1707,7 @@ resolution-markers = [
1710
1707
  ]
1711
1708
  dependencies = [
1712
1709
  { name = "coverage", extra = ["toml"], marker = "python_full_version >= '3.9'" },
1713
- { name = "pytest", version = "8.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" },
1710
+ { name = "pytest", version = "8.3.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" },
1714
1711
  ]
1715
1712
  sdist = { url = "https://files.pythonhosted.org/packages/be/45/9b538de8cef30e17c7b45ef42f538a94889ed6a16f2387a6c89e73220651/pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0", size = 66945 }
1716
1713
  wheels = [
@@ -1743,7 +1740,7 @@ resolution-markers = [
1743
1740
  ]
1744
1741
  dependencies = [
1745
1742
  { name = "httpx", version = "0.27.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" },
1746
- { name = "pytest", version = "8.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" },
1743
+ { name = "pytest", version = "8.3.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" },
1747
1744
  ]
1748
1745
  sdist = { url = "https://files.pythonhosted.org/packages/6c/09/4f61bf814a7bbfcc7e9fe8fd30ad3e5e11cdcf38060a724ee2169339e6ea/pytest_httpx-0.33.0.tar.gz", hash = "sha256:4af9ab0dae5e9c14cb1e27d18af3db1f627b2cf3b11c02b34ddf26aff6b0a24c", size = 51708 }
1749
1746
  wheels = [
@@ -1756,7 +1753,7 @@ version = "3.14.0"
1756
1753
  source = { registry = "https://pypi.org/simple" }
1757
1754
  dependencies = [
1758
1755
  { name = "pytest", version = "7.4.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" },
1759
- { name = "pytest", version = "8.3.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" },
1756
+ { name = "pytest", version = "8.3.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" },
1760
1757
  ]
1761
1758
  sdist = { url = "https://files.pythonhosted.org/packages/c6/90/a955c3ab35ccd41ad4de556596fa86685bf4fc5ffcc62d22d856cfd4e29a/pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0", size = 32814 }
1762
1759
  wheels = [
@@ -2006,63 +2003,63 @@ wheels = [
2006
2003
 
2007
2004
  [[package]]
2008
2005
  name = "rich-click"
2009
- version = "1.8.4"
2006
+ version = "1.8.5"
2010
2007
  source = { registry = "https://pypi.org/simple" }
2011
2008
  dependencies = [
2012
2009
  { name = "click" },
2013
2010
  { name = "rich" },
2014
2011
  { name = "typing-extensions" },
2015
2012
  ]
2016
- sdist = { url = "https://files.pythonhosted.org/packages/fc/f4/e48dc2850662526a26fb0961aacb0162c6feab934312b109b748ae4efee2/rich_click-1.8.4.tar.gz", hash = "sha256:0f49471f04439269d0e66a6f43120f52d11d594869a2a0be600cfb12eb0616b9", size = 38247 }
2013
+ sdist = { url = "https://files.pythonhosted.org/packages/9a/31/103501e85e885e3e202c087fa612cfe450693210372766552ce1ab5b57b9/rich_click-1.8.5.tar.gz", hash = "sha256:a3eebe81da1c9da3c32f3810017c79bd687ff1b3fa35bfc9d8a3338797f1d1a1", size = 38229 }
2017
2014
  wheels = [
2018
- { url = "https://files.pythonhosted.org/packages/84/f3/72f93d8494ee641bde76bfe1208cf4abc44c6f9448673762f6077bc162d6/rich_click-1.8.4-py3-none-any.whl", hash = "sha256:2d2841b3cebe610d5682baa1194beaf78ab00c4fa31931533261b5eba2ee80b7", size = 35071 },
2015
+ { url = "https://files.pythonhosted.org/packages/aa/0b/e2de98c538c0ee9336211d260f88b7e69affab44969750aaca0b48a697c8/rich_click-1.8.5-py3-none-any.whl", hash = "sha256:0fab7bb5b66c15da17c210b4104277cd45f3653a7322e0098820a169880baee0", size = 35081 },
2019
2016
  ]
2020
2017
 
2021
2018
  [[package]]
2022
2019
  name = "ruff"
2023
- version = "0.8.1"
2024
- source = { registry = "https://pypi.org/simple" }
2025
- sdist = { url = "https://files.pythonhosted.org/packages/95/d0/8ff5b189d125f4260f2255d143bf2fa413b69c2610c405ace7a0a8ec81ec/ruff-0.8.1.tar.gz", hash = "sha256:3583db9a6450364ed5ca3f3b4225958b24f78178908d5c4bc0f46251ccca898f", size = 3313222 }
2026
- wheels = [
2027
- { url = "https://files.pythonhosted.org/packages/a2/d6/1a6314e568db88acdbb5121ed53e2c52cebf3720d3437a76f82f923bf171/ruff-0.8.1-py3-none-linux_armv6l.whl", hash = "sha256:fae0805bd514066f20309f6742f6ee7904a773eb9e6c17c45d6b1600ca65c9b5", size = 10532605 },
2028
- { url = "https://files.pythonhosted.org/packages/89/a8/a957a8812e31facffb6a26a30be0b5b4af000a6e30c7d43a22a5232a3398/ruff-0.8.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b8a4f7385c2285c30f34b200ca5511fcc865f17578383db154e098150ce0a087", size = 10278243 },
2029
- { url = "https://files.pythonhosted.org/packages/a8/23/9db40fa19c453fabf94f7a35c61c58f20e8200b4734a20839515a19da790/ruff-0.8.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:cd054486da0c53e41e0086e1730eb77d1f698154f910e0cd9e0d64274979a209", size = 9917739 },
2030
- { url = "https://files.pythonhosted.org/packages/e2/a0/6ee2d949835d5701d832fc5acd05c0bfdad5e89cfdd074a171411f5ccad5/ruff-0.8.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2029b8c22da147c50ae577e621a5bfbc5d1fed75d86af53643d7a7aee1d23871", size = 10779153 },
2031
- { url = "https://files.pythonhosted.org/packages/7a/25/9c11dca9404ef1eb24833f780146236131a3c7941de394bc356912ef1041/ruff-0.8.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2666520828dee7dfc7e47ee4ea0d928f40de72056d929a7c5292d95071d881d1", size = 10304387 },
2032
- { url = "https://files.pythonhosted.org/packages/c8/b9/84c323780db1b06feae603a707d82dbbd85955c8c917738571c65d7d5aff/ruff-0.8.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:333c57013ef8c97a53892aa56042831c372e0bb1785ab7026187b7abd0135ad5", size = 11360351 },
2033
- { url = "https://files.pythonhosted.org/packages/6b/e1/9d4bbb2ace7aad14ded20e4674a48cda5b902aed7a1b14e6b028067060c4/ruff-0.8.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:288326162804f34088ac007139488dcb43de590a5ccfec3166396530b58fb89d", size = 12022879 },
2034
- { url = "https://files.pythonhosted.org/packages/75/28/752ff6120c0e7f9981bc4bc275d540c7f36db1379ba9db9142f69c88db21/ruff-0.8.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b12c39b9448632284561cbf4191aa1b005882acbc81900ffa9f9f471c8ff7e26", size = 11610354 },
2035
- { url = "https://files.pythonhosted.org/packages/ba/8c/967b61c2cc8ebd1df877607fbe462bc1e1220b4a30ae3352648aec8c24bd/ruff-0.8.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:364e6674450cbac8e998f7b30639040c99d81dfb5bbc6dfad69bc7a8f916b3d1", size = 12813976 },
2036
- { url = "https://files.pythonhosted.org/packages/7f/29/e059f945d6bd2d90213387b8c360187f2fefc989ddcee6bbf3c241329b92/ruff-0.8.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b22346f845fec132aa39cd29acb94451d030c10874408dbf776af3aaeb53284c", size = 11154564 },
2037
- { url = "https://files.pythonhosted.org/packages/55/47/cbd05e5a62f3fb4c072bc65c1e8fd709924cad1c7ec60a1000d1e4ee8307/ruff-0.8.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b2f2f7a7e7648a2bfe6ead4e0a16745db956da0e3a231ad443d2a66a105c04fa", size = 10760604 },
2038
- { url = "https://files.pythonhosted.org/packages/bb/ee/4c3981c47147c72647a198a94202633130cfda0fc95cd863a553b6f65c6a/ruff-0.8.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:adf314fc458374c25c5c4a4a9270c3e8a6a807b1bec018cfa2813d6546215540", size = 10391071 },
2039
- { url = "https://files.pythonhosted.org/packages/6b/e6/083eb61300214590b188616a8ac6ae1ef5730a0974240fb4bec9c17de78b/ruff-0.8.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a885d68342a231b5ba4d30b8c6e1b1ee3a65cf37e3d29b3c74069cdf1ee1e3c9", size = 10896657 },
2040
- { url = "https://files.pythonhosted.org/packages/77/bd/aacdb8285d10f1b943dbeb818968efca35459afc29f66ae3bd4596fbf954/ruff-0.8.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d2c16e3508c8cc73e96aa5127d0df8913d2290098f776416a4b157657bee44c5", size = 11228362 },
2041
- { url = "https://files.pythonhosted.org/packages/39/72/fcb7ad41947f38b4eaa702aca0a361af0e9c2bf671d7fd964480670c297e/ruff-0.8.1-py3-none-win32.whl", hash = "sha256:93335cd7c0eaedb44882d75a7acb7df4b77cd7cd0d2255c93b28791716e81790", size = 8803476 },
2042
- { url = "https://files.pythonhosted.org/packages/e4/ea/cae9aeb0f4822c44651c8407baacdb2e5b4dcd7b31a84e1c5df33aa2cc20/ruff-0.8.1-py3-none-win_amd64.whl", hash = "sha256:2954cdbe8dfd8ab359d4a30cd971b589d335a44d444b6ca2cb3d1da21b75e4b6", size = 9614463 },
2043
- { url = "https://files.pythonhosted.org/packages/eb/76/fbb4bd23dfb48fa7758d35b744413b650a9fd2ddd93bca77e30376864414/ruff-0.8.1-py3-none-win_arm64.whl", hash = "sha256:55873cc1a473e5ac129d15eccb3c008c096b94809d693fc7053f588b67822737", size = 8959621 },
2020
+ version = "0.8.2"
2021
+ source = { registry = "https://pypi.org/simple" }
2022
+ sdist = { url = "https://files.pythonhosted.org/packages/5e/2b/01245f4f3a727d60bebeacd7ee6d22586c7f62380a2597ddb22c2f45d018/ruff-0.8.2.tar.gz", hash = "sha256:b84f4f414dda8ac7f75075c1fa0b905ac0ff25361f42e6d5da681a465e0f78e5", size = 3349020 }
2023
+ wheels = [
2024
+ { url = "https://files.pythonhosted.org/packages/91/29/366be70216dba1731a00a41f2f030822b0c96c7c4f3b2c0cdce15cbace74/ruff-0.8.2-py3-none-linux_armv6l.whl", hash = "sha256:c49ab4da37e7c457105aadfd2725e24305ff9bc908487a9bf8d548c6dad8bb3d", size = 10530649 },
2025
+ { url = "https://files.pythonhosted.org/packages/63/82/a733956540bb388f00df5a3e6a02467b16c0e529132625fe44ce4c5fb9c7/ruff-0.8.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ec016beb69ac16be416c435828be702ee694c0d722505f9c1f35e1b9c0cc1bf5", size = 10274069 },
2026
+ { url = "https://files.pythonhosted.org/packages/3d/12/0b3aa14d1d71546c988a28e1b412981c1b80c8a1072e977a2f30c595cc4a/ruff-0.8.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f05cdf8d050b30e2ba55c9b09330b51f9f97d36d4673213679b965d25a785f3c", size = 9909400 },
2027
+ { url = "https://files.pythonhosted.org/packages/23/08/f9f08cefb7921784c891c4151cce6ed357ff49e84b84978440cffbc87408/ruff-0.8.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60f578c11feb1d3d257b2fb043ddb47501ab4816e7e221fbb0077f0d5d4e7b6f", size = 10766782 },
2028
+ { url = "https://files.pythonhosted.org/packages/e4/71/bf50c321ec179aa420c8ec40adac5ae9cc408d4d37283a485b19a2331ceb/ruff-0.8.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cbd5cf9b0ae8f30eebc7b360171bd50f59ab29d39f06a670b3e4501a36ba5897", size = 10286316 },
2029
+ { url = "https://files.pythonhosted.org/packages/f2/83/c82688a2a6117539aea0ce63fdf6c08e60fe0202779361223bcd7f40bd74/ruff-0.8.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b402ddee3d777683de60ff76da801fa7e5e8a71038f57ee53e903afbcefdaa58", size = 11338270 },
2030
+ { url = "https://files.pythonhosted.org/packages/7f/d7/bc6a45e5a22e627640388e703160afb1d77c572b1d0fda8b4349f334fc66/ruff-0.8.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:705832cd7d85605cb7858d8a13d75993c8f3ef1397b0831289109e953d833d29", size = 12058579 },
2031
+ { url = "https://files.pythonhosted.org/packages/da/3b/64150c93946ec851e6f1707ff586bb460ca671581380c919698d6a9267dc/ruff-0.8.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:32096b41aaf7a5cc095fa45b4167b890e4c8d3fd217603f3634c92a541de7248", size = 11615172 },
2032
+ { url = "https://files.pythonhosted.org/packages/e4/9e/cf12b697ea83cfe92ec4509ae414dc4c9b38179cc681a497031f0d0d9a8e/ruff-0.8.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e769083da9439508833cfc7c23e351e1809e67f47c50248250ce1ac52c21fb93", size = 12882398 },
2033
+ { url = "https://files.pythonhosted.org/packages/a9/27/96d10863accf76a9c97baceac30b0a52d917eb985a8ac058bd4636aeede0/ruff-0.8.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fe716592ae8a376c2673fdfc1f5c0c193a6d0411f90a496863c99cd9e2ae25d", size = 11176094 },
2034
+ { url = "https://files.pythonhosted.org/packages/eb/10/cd2fd77d4a4e7f03c29351be0f53278a393186b540b99df68beb5304fddd/ruff-0.8.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:81c148825277e737493242b44c5388a300584d73d5774defa9245aaef55448b0", size = 10771884 },
2035
+ { url = "https://files.pythonhosted.org/packages/71/5d/beabb2ff18870fc4add05fa3a69a4cb1b1d2d6f83f3cf3ae5ab0d52f455d/ruff-0.8.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d261d7850c8367704874847d95febc698a950bf061c9475d4a8b7689adc4f7fa", size = 10382535 },
2036
+ { url = "https://files.pythonhosted.org/packages/ae/29/6b3fdf3ad3e35b28d87c25a9ff4c8222ad72485ab783936b2b267250d7a7/ruff-0.8.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1ca4e3a87496dc07d2427b7dd7ffa88a1e597c28dad65ae6433ecb9f2e4f022f", size = 10886995 },
2037
+ { url = "https://files.pythonhosted.org/packages/e9/dc/859d889b4d9356a1a2cdbc1e4a0dda94052bc5b5300098647e51a58c430b/ruff-0.8.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:729850feed82ef2440aa27946ab39c18cb4a8889c1128a6d589ffa028ddcfc22", size = 11220750 },
2038
+ { url = "https://files.pythonhosted.org/packages/0b/08/e8f519f61f1d624264bfd6b8829e4c5f31c3c61193bc3cff1f19dbe7626a/ruff-0.8.2-py3-none-win32.whl", hash = "sha256:ac42caaa0411d6a7d9594363294416e0e48fc1279e1b0e948391695db2b3d5b1", size = 8729396 },
2039
+ { url = "https://files.pythonhosted.org/packages/f8/d4/ba1c7ab72aba37a2b71fe48ab95b80546dbad7a7f35ea28cf66fc5cea5f6/ruff-0.8.2-py3-none-win_amd64.whl", hash = "sha256:2aae99ec70abf43372612a838d97bfe77d45146254568d94926e8ed5bbb409ea", size = 9594729 },
2040
+ { url = "https://files.pythonhosted.org/packages/23/34/db20e12d3db11b8a2a8874258f0f6d96a9a4d631659d54575840557164c8/ruff-0.8.2-py3-none-win_arm64.whl", hash = "sha256:fb88e2a506b70cfbc2de6fae6681c4f944f7dd5f2fe87233a7233d888bad73e8", size = 9035131 },
2044
2041
  ]
2045
2042
 
2046
2043
  [[package]]
2047
2044
  name = "sentry-sdk"
2048
- version = "2.19.0"
2045
+ version = "2.19.2"
2049
2046
  source = { registry = "https://pypi.org/simple" }
2050
2047
  dependencies = [
2051
2048
  { name = "certifi" },
2052
2049
  { name = "urllib3" },
2053
2050
  ]
2054
- sdist = { url = "https://files.pythonhosted.org/packages/a2/0e/cc0e60f0e0cfd5a9e42622ff5a227301c6475a56bcfa82e8e893bc209f20/sentry_sdk-2.19.0.tar.gz", hash = "sha256:ee4a4d2ae8bfe3cac012dcf3e4607975904c137e1738116549fc3dbbb6ff0e36", size = 298045 }
2051
+ sdist = { url = "https://files.pythonhosted.org/packages/36/4a/eccdcb8c2649d53440ae1902447b86e2e2ad1bc84207c80af9696fa07614/sentry_sdk-2.19.2.tar.gz", hash = "sha256:467df6e126ba242d39952375dd816fbee0f217d119bf454a8ce74cf1e7909e8d", size = 299047 }
2055
2052
  wheels = [
2056
- { url = "https://files.pythonhosted.org/packages/c6/6b/191ca63f05d3ecc7600b5b3abd493a4c1b8468289c9737a7735ade1fedca/sentry_sdk-2.19.0-py2.py3-none-any.whl", hash = "sha256:7b0b3b709dee051337244a09a30dbf6e95afe0d34a1f8b430d45e0982a7c125b", size = 322158 },
2053
+ { url = "https://files.pythonhosted.org/packages/31/4d/74597bb6bcc23abc774b8901277652c61331a9d4d0a8d1bdb20679b9bbcb/sentry_sdk-2.19.2-py2.py3-none-any.whl", hash = "sha256:ebdc08228b4d131128e568d696c210d846e5b9d70aa0327dec6b1272d9d40b84", size = 322942 },
2057
2054
  ]
2058
2055
 
2059
2056
  [[package]]
2060
2057
  name = "six"
2061
- version = "1.16.0"
2058
+ version = "1.17.0"
2062
2059
  source = { registry = "https://pypi.org/simple" }
2063
- sdist = { url = "https://files.pythonhosted.org/packages/71/39/171f1c67cd00715f190ba0b100d606d440a28c93c7714febeca8b79af85e/six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", size = 34041 }
2060
+ sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 }
2064
2061
  wheels = [
2065
- { url = "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", size = 11053 },
2062
+ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 },
2066
2063
  ]
2067
2064
 
2068
2065
  [[package]]
@@ -2248,11 +2245,11 @@ wheels = [
2248
2245
 
2249
2246
  [[package]]
2250
2247
  name = "types-six"
2251
- version = "1.16.21.20241105"
2248
+ version = "1.17.0.20241205"
2252
2249
  source = { registry = "https://pypi.org/simple" }
2253
- sdist = { url = "https://files.pythonhosted.org/packages/09/d6/fbea3d9fc8388abd98081c33ae4ca9ed5b11e947409ccbf85467df49bfe4/types-six-1.16.21.20241105.tar.gz", hash = "sha256:ce3534c38079ec3242f4a20376283eb265a3837f80592b0ecacb14bd41acc29e", size = 10523 }
2250
+ sdist = { url = "https://files.pythonhosted.org/packages/ca/01/1e1088033a79faa46d1b0761b5b00f2d50e5f89c567a140d55b79d1f2658/types_six-1.17.0.20241205.tar.gz", hash = "sha256:1f662347a8f3b2bf30517d629d82f591420df29811794b0bf3804e14d716f6e0", size = 15460 }
2254
2251
  wheels = [
2255
- { url = "https://files.pythonhosted.org/packages/4e/1f/5d6b57b58591f7f70ee7cee6c804280d60ab9ffe5968f205519c0ff9bf3a/types_six-1.16.21.20241105-py3-none-any.whl", hash = "sha256:8b4b29e5c8fe7f1131be8f3cb7cedbcd8bb889707336f32c3fb332c9b1c71991", size = 15371 },
2252
+ { url = "https://files.pythonhosted.org/packages/96/c6/67812fcc6c4d6cb469a7f38a293ad6d6effcfb4b599eb0f1ba287878ec0f/types_six-1.17.0.20241205-py3-none-any.whl", hash = "sha256:a4947c2bdcd9ab69d44466a533a15839ff48ddc27223615cb8145d73ab805bc2", size = 20068 },
2256
2253
  ]
2257
2254
 
2258
2255
  [[package]]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes