djcheckup 0.2.0__tar.gz → 0.2.1__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: djcheckup
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: DJ Checkup is a security scanner for Django sites.
5
5
  Author: Stuart Maxwell
6
6
  Author-email: Stuart Maxwell <stuart@amanzi.nz>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "djcheckup"
3
- version = "0.2.0"
3
+ version = "0.2.1"
4
4
  description = "DJ Checkup is a security scanner for Django sites."
5
5
  readme = "README.md"
6
6
  authors = [{ name = "Stuart Maxwell", email = "stuart@amanzi.nz" }]
@@ -4,7 +4,7 @@ from abc import ABC, abstractmethod
4
4
  from dataclasses import dataclass
5
5
  from enum import Enum
6
6
  from http.cookiejar import CookieJar
7
- from typing import Literal
7
+ from typing import Literal, Self
8
8
 
9
9
  import httpx
10
10
 
@@ -289,20 +289,52 @@ class SchemeCheck(_BaseCheck):
289
289
  class SiteChecker:
290
290
  """Run all the checks for a given site."""
291
291
 
292
- def __init__(self, url: str) -> None:
293
- """Initialize the SiteChecker with a URL."""
292
+ def __init__(
293
+ self,
294
+ url: str,
295
+ *,
296
+ client: httpx.Client | None = None,
297
+ user_agent: str = "DJCheckupBot/1.0 (+https://pypi.org/project/djcheckup/)",
298
+ timeout: float = 10.0,
299
+ follow_redirects: bool = True,
300
+ ) -> None:
301
+ """Initialize the SiteChecker with a URL and optional HTTPX client.
302
+
303
+ Args:
304
+ url: The URL to check.
305
+ client: An optional HTTPX client to use for requests.
306
+ user_agent: The User-Agent string to use for requests.
307
+ timeout: The timeout for requests in seconds.
308
+ follow_redirects: Whether to follow redirects.
309
+ """
294
310
  self.url: httpx.URL = httpx.URL(url)
295
- self.user_agent: str = "DJCheckupBot/1.0 (+https://djcheckup.com/bot-info)"
296
- self.timeout: float = 10.0
297
- self.client: httpx.Client = httpx.Client(
298
- headers={"User-Agent": self.user_agent},
299
- timeout=self.timeout,
300
- follow_redirects=True,
301
- )
311
+ self._client_provided = client is not None
312
+
313
+ if client is not None:
314
+ self.client = client
315
+ else:
316
+ self.client = httpx.Client(
317
+ headers={"User-Agent": user_agent},
318
+ timeout=timeout,
319
+ follow_redirects=follow_redirects,
320
+ )
302
321
 
303
322
  def close(self) -> None:
304
- """Close the HTTP client and release resources."""
305
- self.client.close()
323
+ """Close the HTTP client and release resources.
324
+
325
+ Only close the client if it was created by this instance.
326
+ """
327
+ if not self._client_provided:
328
+ self.client.close()
329
+
330
+ # Context manager support for automatic cleanup
331
+ def __enter__(self) -> Self:
332
+ """Context manager entry."""
333
+ return self
334
+
335
+ def __exit__(self, exc_type, exc_val, exc_tb) -> None: # noqa: ANN001
336
+ """Context manager exit."""
337
+ self.close()
306
338
 
307
339
  def run_first_check(self) -> CheckResponse:
308
340
  """Run the first check.
@@ -360,6 +392,4 @@ class SiteChecker:
360
392
  site_check_results.check_results.append(result)
361
393
  previous_results[check.check_id] = result
362
394
 
363
- # Close the HTTP client
364
- self.client.close()
365
395
  return site_check_results
@@ -15,8 +15,8 @@ def run_checks(url: str, output_format: Literal["json"]) -> str: ...
15
15
 
16
16
  def run_checks(url: str, output_format: Literal["object", "json"] = "object") -> str | SiteCheckResult:
17
17
  """Run the DJ Checkup tool against a specific URL and returns a JSON string."""
18
- checker = SiteChecker(url)
19
- results = checker.run_checks(all_checks)
18
+ with SiteChecker(url) as checker:
19
+ results = checker.run_checks(all_checks)
20
20
 
21
21
  if output_format not in {"object", "json"}:
22
22
  msg = f"Invalid output_format: {output_format!r}. Must be 'object' or 'json'."
File without changes
File without changes