diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d7d5f9..35852a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.6.1 - 2026-11-05 + +The `X-Search1API-Client` request header now reports the installed version (`python/0.6.1`). Since 0.3.0 it had always said `python/0.3.0`. The version lives in `search1api/_version.py` and a test keeps it equal to `pyproject.toml`. No API changes. + ## 0.6.0 - 2026-11-05 Adds keyword arguments to `start_deepcrawl` and `deepcrawl` on `Search1API` and `AsyncSearch1API`: `max_pages` (1-1000, default 1000, applied after the path rules in discovery order), `include_paths` and `exclude_paths` (up to 20 URL path rules each; a rule without `*` is a path prefix on segment boundaries, a rule with `*` matches the whole path; exclusion wins) and `format` (`"zip"`, the default, or `"json"`). Unset arguments are not sent. `DeepcrawlStatusResponse` adds `format`, `stats` (`discovered`, `matched`, `skipped`, `crawled`, `failed`), `failed` (`url`, `error`) and, for `format="json"`, `resultUrl` and `pages` (`url`, `title`, Markdown `content`; omitted above 5 MB, use `resultUrl`). Still 20 credits per task. The bundled OpenAPI snapshot is re-synced with the live contract. diff --git a/pyproject.toml b/pyproject.toml index f5cdd01..3a61c2f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "search1api" -version = "0.6.0" +version = "0.6.1" description = "Official Python client for Search1API" readme = "README.md" license = { file = "LICENSE" } diff --git a/src/search1api/__init__.py b/src/search1api/__init__.py index 57cbc02..0cce22b 100644 --- a/src/search1api/__init__.py +++ b/src/search1api/__init__.py @@ -1,3 +1,4 @@ +from ._version import __version__ as __version__ from .client import AsyncSearch1API, Search1API from .errors import ( APIConnectionError, @@ -34,5 +35,3 @@ "Search1APIError", "UnprocessableEntityError", ] - -__version__ = "0.6.0" diff --git a/src/search1api/_version.py b/src/search1api/_version.py new file mode 100644 index 0000000..951860b --- /dev/null +++ b/src/search1api/_version.py @@ -0,0 +1,3 @@ +# Sent as ``X-Search1API-Client: python/``. Kept equal to the version +# in pyproject.toml by tests/test_client.py; bump both together. +__version__ = "0.6.1" diff --git a/src/search1api/client.py b/src/search1api/client.py index 1175f0d..bdfa0b8 100644 --- a/src/search1api/client.py +++ b/src/search1api/client.py @@ -11,6 +11,7 @@ import httpx +from ._version import __version__ from .errors import ( APIConnectionError, APITimeoutError, @@ -252,7 +253,7 @@ def _request_headers(self, accept: str = "application/json") -> Dict[str, str]: return { "Accept": accept, "Authorization": f"Bearer {self.api_key}", - "X-Search1API-Client": "python/0.3.0", + "X-Search1API-Client": f"python/{__version__}", **self.headers, } diff --git a/tests/test_client.py b/tests/test_client.py index 5598d9c..60586df 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -1,5 +1,6 @@ import asyncio import json +import re from pathlib import Path import httpx @@ -11,6 +12,7 @@ InternalServerError, Search1API, Search1APIConfigurationError, + __version__, ) @@ -622,3 +624,25 @@ def test_sdk_covers_every_public_openapi_operation(): for method in operation_methods.values(): assert callable(getattr(Search1API, method)) assert callable(getattr(AsyncSearch1API, method)) + + +def test_version_matches_pyproject(): + pyproject = (Path(__file__).resolve().parents[1] / "pyproject.toml").read_text() + match = re.search(r'^version = "([^"]+)"$', pyproject, re.M) + assert match is not None + assert __version__ == match.group(1) + + +def test_client_header_reports_package_version(): + seen = [] + + def handler(request): + seen.append(request) + return json_response(200, {"links": []}, request) + + http_client = httpx.Client(transport=httpx.MockTransport(handler)) + client = Search1API("test-key", client=http_client) + + client.sitemap("https://example.com") + + assert seen[0].headers["X-Search1API-Client"] == f"python/{__version__}"