logdetective 2.9.0__py3-none-any.whl → 2.10.0__py3-none-any.whl

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.
@@ -10,6 +10,7 @@ from pydantic import (
10
10
  field_validator,
11
11
  NonNegativeFloat,
12
12
  HttpUrl,
13
+ PrivateAttr,
13
14
  )
14
15
 
15
16
  import aiohttp
@@ -183,8 +184,8 @@ class InferenceConfig(BaseModel): # pylint: disable=too-many-instance-attribute
183
184
  user_role: str = USER_ROLE_DEFAULT
184
185
  system_role: str = SYSTEM_ROLE_DEFAULT
185
186
  llm_api_timeout: float = 15.0
186
- _http_session: aiohttp.ClientSession = None
187
- _limiter: AsyncLimiter = AsyncLimiter(LLM_DEFAULT_REQUESTS_PER_MINUTE)
187
+ _limiter: AsyncLimiter = PrivateAttr(
188
+ default_factory=lambda: AsyncLimiter(LLM_DEFAULT_REQUESTS_PER_MINUTE))
188
189
 
189
190
  def __init__(self, data: Optional[dict] = None):
190
191
  super().__init__()
@@ -207,40 +208,6 @@ class InferenceConfig(BaseModel): # pylint: disable=too-many-instance-attribute
207
208
  self.llm_api_timeout = data.get("llm_api_timeout", 15.0)
208
209
  self._limiter = AsyncLimiter(self._requests_per_minute)
209
210
 
210
- def __del__(self):
211
- # Close connection when this object is destroyed
212
- if self._http_session:
213
- try:
214
- loop = asyncio.get_running_loop()
215
- loop.create_task(self._http_session.close())
216
- except RuntimeError:
217
- # No loop running, so create one to close the session
218
- loop = asyncio.new_event_loop()
219
- loop.run_until_complete(self._http_session.close())
220
- loop.close()
221
- except Exception: # pylint: disable=broad-exception-caught
222
- # We should only get here if we're shutting down, so we don't
223
- # really care if the close() completes cleanly.
224
- pass
225
-
226
- def get_http_session(self):
227
- """Return the internal HTTP session so it can be used to contect the
228
- LLM server. May be used as a context manager."""
229
-
230
- # Create the session on the first attempt. We need to do this "lazily"
231
- # because it needs to happen once the event loop is running, even
232
- # though the initialization itself is synchronous.
233
- if not self._http_session:
234
- self._http_session = aiohttp.ClientSession(
235
- base_url=self.url,
236
- timeout=aiohttp.ClientTimeout(
237
- total=self.http_timeout,
238
- connect=3.07,
239
- ),
240
- )
241
-
242
- return self._http_session
243
-
244
211
  def get_limiter(self):
245
212
  """Return the limiter object so it can be used as a context manager"""
246
213
  return self._limiter
@@ -254,7 +221,7 @@ class ExtractorConfig(BaseModel):
254
221
  max_snippet_len: int = 2000
255
222
  csgrep: bool = False
256
223
 
257
- _extractors: List[Extractor] = []
224
+ _extractors: List[Extractor] = PrivateAttr(default_factory=list)
258
225
 
259
226
  def _setup_extractors(self):
260
227
  """Initialize extractors with common settings."""
@@ -322,8 +289,8 @@ class GitLabInstanceConfig(BaseModel): # pylint: disable=too-many-instance-attr
322
289
  webhook_secrets: Optional[List[str]] = None
323
290
 
324
291
  timeout: float = 5.0
325
- _conn: Gitlab = None
326
- _http_session: aiohttp.ClientSession = None
292
+ _conn: Gitlab | None = PrivateAttr(default=None)
293
+ _http_session: aiohttp.ClientSession | None = PrivateAttr(default=None)
327
294
 
328
295
  # Maximum size of artifacts.zip in MiB. (default: 300 MiB)
329
296
  max_artifact_size: int = 300 * 1024 * 1024
@@ -409,8 +376,8 @@ class KojiInstanceConfig(BaseModel):
409
376
  xmlrpc_url: str = ""
410
377
  tokens: List[str] = []
411
378
 
412
- _conn: Optional[koji.ClientSession] = None
413
- _callbacks: defaultdict[int, set[str]] = defaultdict(set)
379
+ _conn: Optional[koji.ClientSession] = PrivateAttr(default=None)
380
+ _callbacks: defaultdict[int, set[str]] = PrivateAttr(default_factory=lambda: defaultdict(set))
414
381
 
415
382
  def __init__(self, name: str, data: Optional[dict] = None):
416
383
  super().__init__()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: logdetective
3
- Version: 2.9.0
3
+ Version: 2.10.0
4
4
  Summary: Log using LLM AI to search for build/test failures and provide ideas for fixing these.
5
5
  License: Apache-2.0
6
6
  License-File: LICENSE
@@ -28,7 +28,7 @@ Requires-Dist: aiolimiter (>=1.0.0,<2.0.0) ; extra == "server"
28
28
  Requires-Dist: aioresponses (>=0.7.8,<0.8.0) ; extra == "testing"
29
29
  Requires-Dist: alembic (>=1.13.3,<2.0.0) ; extra == "server" or extra == "server-testing"
30
30
  Requires-Dist: asciidoc[testing] (>=10.2.1,<11.0.0) ; extra == "testing"
31
- Requires-Dist: asyncpg (>=0.30.0,<0.31.0) ; extra == "server" or extra == "server-testing"
31
+ Requires-Dist: asyncpg (>=0.30.0,<1.0.0) ; extra == "server" or extra == "server-testing"
32
32
  Requires-Dist: backoff (==2.2.1) ; extra == "server" or extra == "server-testing"
33
33
  Requires-Dist: drain3 (>=0.9.11,<0.10.0)
34
34
  Requires-Dist: fastapi (>=0.111.1,<1.0.0) ; extra == "server" or extra == "server-testing"
@@ -24,7 +24,7 @@ logdetective/server/gitlab.py,sha256=putpnf8PfGsCZJsqWZA1rMovRGnyagoQmgpKLqtA-aQ
24
24
  logdetective/server/koji.py,sha256=LG1pRiKUFvYFRKzgQoUG3pUHfcEwMoaMNjUSMKw_pBA,5640
25
25
  logdetective/server/llm.py,sha256=bmA6LsV80OdO60q4WLoKuehuVDEYq-HhBAYcZeLfrv8,10150
26
26
  logdetective/server/metric.py,sha256=wLOpgcAch3rwhPA5P2YWUeMNAPsvRGseRjH5HlTb7JM,4529
27
- logdetective/server/models.py,sha256=V2QCKF_zB9FLaZjiBnUlmOZc5c8SsS4uhUmxrhqcJSY,21098
27
+ logdetective/server/models.py,sha256=AJyycAEEl2o6TH4eAqVMlt5woqAB5M8ze2L575leA_I,19835
28
28
  logdetective/server/plot.py,sha256=8LERgY3vQckaHZV2PZfOrZT8CjCAiji57QCmRW24Rfo,14697
29
29
  logdetective/server/server.py,sha256=JueU-5c8t9h1CZy4gtoEeT8VSEirpeS0K3wrfqTPvAc,25381
30
30
  logdetective/server/templates/base_response.html.j2,sha256=BJGGV_Xb0Lnue8kq32oG9lI5CQDf9vce7HMYsP-Pvb4,2040
@@ -33,8 +33,8 @@ logdetective/server/templates/gitlab_short_comment.md.j2,sha256=2krnMlGqqju2V_6p
33
33
  logdetective/server/utils.py,sha256=0BZ8WmzXNEtkUty1kOyFbBxDZWL0Icc8BUrxuHw9uvs,4015
34
34
  logdetective/skip_snippets.yml,sha256=reGlhPPCo06nNUJWiC2LY-OJOoPdcyOB7QBTSMeh0eg,487
35
35
  logdetective/utils.py,sha256=yalhySOF_Gzmqx_Ft9qad3TplAfZ6LOmauGXEJfKWiE,9803
36
- logdetective-2.9.0.dist-info/METADATA,sha256=cTc0MOpLusXA5aQ7qH_lHFr3IuQMldFiL5Sgc17XIUU,23273
37
- logdetective-2.9.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
38
- logdetective-2.9.0.dist-info/entry_points.txt,sha256=3K_vXja6PmcA8sNdUi63WdImeiNhVZcEGPTaoJmltfA,63
39
- logdetective-2.9.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
40
- logdetective-2.9.0.dist-info/RECORD,,
36
+ logdetective-2.10.0.dist-info/METADATA,sha256=ii3l-h7Tpnc9BByVL1BYDj8XkbzKuqD1YW-A4gbm66E,23273
37
+ logdetective-2.10.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
38
+ logdetective-2.10.0.dist-info/entry_points.txt,sha256=3K_vXja6PmcA8sNdUi63WdImeiNhVZcEGPTaoJmltfA,63
39
+ logdetective-2.10.0.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
40
+ logdetective-2.10.0.dist-info/RECORD,,