Added
- Added max_response_bytes constructor argument to cap raw and decompressed response size (guards against decompression bombs; None = no limit, default behavior unchanged)
- Added vulners.version re-export and all on the package root
- Added PEP 561 py.typed marker for inline type annotations
- Added typing-extensions and typing-inspection as direct dependencies
- Added VulnersApiError.retry_after, populated from the Retry-After header
- Added VulnersApiError.message / .error_code parsing across v3, v4 and plain-text error shapes
- Added VulnersDeprecationWarning and PEP 702 deprecated markers on deprecated methods
- Added close() and context-manager support (with VulnersApi(key) as api:) to VulnersApi / VScannerApi
- Added SPDX GPL-3.0-only license and project URLs to package metadata
Changed
- import vulners no longer flips the global DeprecationWarning filter (scoped to VulnersDeprecationWarning)
- Rate-limit buckets are now per-instance instead of shared at class level
- Request bodies are serialized with orjson (on-wire bytes unchanged)
- Pinned ruff target-version to py310
- Reworked samples/ into task-oriented, live-tested scenarios reading VULNERS_API_KEY
- Documented SubscriptionV4Api.update() as a full-replace (not partial) operation
Fixed
- search_bulletins / search_exploits with offset >= 10000 now raises a clear ValueError instead of a confusing ValidationError
- Audit / subscription field enums accept server-confirmed and arbitrary string values (| str), fixing false ValidationError
- SubscriptionV4Api.get now sends subscription_id (was id, which returned 400)
- import vulners no longer raises PackageNotFoundError when distribution metadata is absent (falls back to "unknown")
- HTTP >= 400 responses with a {"data": ...} body now raise VulnersApiError instead of returning as success
- Gateway error pages (502/503/504) are wrapped in VulnersApiError instead of a raw JSON decode error
- Empty ZIP archives raise RuntimeError instead of IndexError; file handles are closed on every path
- Path parameters are percent-quoted before URL substitution
- RateLimitBucket fixes: no longer hangs on limits below 60 req/min, ignores invalid rate headers, uses a monotonic clock and a lock
- Documented retry_count honestly (retries connection failures only, not HTTP errors / read timeouts)
- Various codegen fixes: inspect.signature, get_type_hints(), sys._getframe-free import, FieldInfo selection
- Deprecation warnings now report the caller's call site and warn exactly once