From 1d5232192cb154b88476aa159e679ac84bdaba0b Mon Sep 17 00:00:00 2001 From: cjumel Date: Mon, 29 Sep 2025 11:00:12 +0200 Subject: [PATCH 1/3] docs: mention async functions in README --- README.md | 48 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2fdbb93..f3c0aa7 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,8 @@ benefit from Linkup services to the full extent. 📝 - ✅ **Simple and intuitive API client.** - 🔍 **Support all Linkup entrypoints and parameters.** -- ⚡ **Supports synchronous and asynchronous requests.** -- 🔒 **Handles authentication and request management.** +- ⚡ **Support synchronous and asynchronous calls.** +- 🔒 **Handle authentication and request management.** ## 📦 Installation @@ -90,9 +90,10 @@ The `search` function also supports three output types: user-defined schema ```python -from linkup import LinkupClient, LinkupSourcedAnswer from typing import Any +from linkup import LinkupClient, LinkupSourcedAnswer + client = LinkupClient() # API key can be read from the environment variable or passed as an argument search_response: Any = client.search( query="What are the 3 major events in the life of Abraham Lincoln?", @@ -149,7 +150,46 @@ Check the code or the [official documentation](https://docs.linkup.so/pages/documentation/api-reference/endpoint/post-fetch) for the detailed list of available parameters. +#### ⌛ Asynchronous Calls + +All the Linkup main functions come with an asynchronous counterpart, with the same behavior and the +same name prefixed by `async_` (e.g. `async_search` for `search`). This should be favored in +production use cases to avoid blocking the main thread while waiting for the Linkup API to respond. +This makes possible to call the Linkup API several times concurrently for instance. + +```python +import asyncio +from typing import Any + +from linkup import LinkupClient, LinkupSourcedAnswer + +async def main() -> None: + client = LinkupClient() # API key can be read from the environment variable or passed as an argument + search_response: Any = await client.async_search( + query="What are the 3 major events in the life of Abraham Lincoln?", + depth="deep", # "standard" or "deep" + output_type="sourcedAnswer", # "searchResults" or "sourcedAnswer" or "structured" + structured_output_schema=None, # must be filled if output_type is "structured" + ) + assert isinstance(search_response, LinkupSourcedAnswer) + print(search_response.model_dump()) + +asyncio.run(main()) +# Response: +# { +# answer="The three major events in the life of Abraham Lincoln are: 1. ...", +# sources=[ +# { +# "name": "HISTORY", +# "url": "https://www.history.com/topics/us-presidents/abraham-lincoln", +# "snippet": "Abraham Lincoln - Facts & Summary - HISTORY ..." +# }, +# ... +# ] +# } +``` + #### 📚 More Examples See the `examples/` directory for more examples and documentation, for instance on how to use Linkup -entrypoints using asynchronous functions. +entrypoints using asynchronous functions to call the Linkup API several times concurrenly. From 02df3e6505a2d1dc715d959c05ea3ff7c93c236f Mon Sep 17 00:00:00 2001 From: cjumel Date: Tue, 30 Sep 2025 16:32:39 +0200 Subject: [PATCH 2/3] docs: add pycodestyle checks --- pyproject.toml | 8 ++++++-- src/linkup/client.py | 2 ++ src/linkup/errors.py | 3 +++ src/linkup/types.py | 2 ++ 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 222a691..0227fdd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,10 +55,14 @@ line-length = 100 target-version = "py39" [tool.ruff.lint] -select = ["E", "F", "I", "S", "UP"] +extend-ignore = ["D107"] +pydocstyle = { convention = "google" } +select = ["D", "E", "F", "I", "S", "UP"] [tool.ruff.lint.extend-per-file-ignores] -"tests/**/*_test.py" = ["S101"] +"examples/*.py" = ["D"] +"src/linkup/__init__.py" = ["D104"] +"tests/**/*test.py" = ["D", "S101"] [build-system] build-backend = "hatchling.build" diff --git a/src/linkup/client.py b/src/linkup/client.py index 6f3a9b0..8779f23 100644 --- a/src/linkup/client.py +++ b/src/linkup/client.py @@ -1,3 +1,5 @@ +"""Linkup client, the entrypoint for Linkup functions.""" + import json import os from datetime import date diff --git a/src/linkup/errors.py b/src/linkup/errors.py index 5d6c108..5f8c6c4 100644 --- a/src/linkup/errors.py +++ b/src/linkup/errors.py @@ -1,3 +1,6 @@ +"""Linkup custom errors.""" + + class LinkupInvalidRequestError(Exception): """Invalid request error, raised when the Linkup API returns a 400 status code. diff --git a/src/linkup/types.py b/src/linkup/types.py index 1038eef..c4a8621 100644 --- a/src/linkup/types.py +++ b/src/linkup/types.py @@ -1,3 +1,5 @@ +"""Input and output types for Linkup functions.""" + from typing import Any, Literal, Optional, Union from pydantic import BaseModel, ConfigDict, Field From 4eca573986686941285d95f05fd10a739256199e Mon Sep 17 00:00:00 2001 From: cjumel Date: Wed, 29 Oct 2025 11:24:48 +0100 Subject: [PATCH 3/3] docs: improve README examples readability --- README.md | 70 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index f3c0aa7..c0711b6 100644 --- a/README.md +++ b/README.md @@ -103,18 +103,22 @@ search_response: Any = client.search( ) assert isinstance(search_response, LinkupSourcedAnswer) print(search_response.model_dump()) -# Response: -# { -# answer="The three major events in the life of Abraham Lincoln are: 1. ...", -# sources=[ -# { -# "name": "HISTORY", -# "url": "https://www.history.com/topics/us-presidents/abraham-lincoln", -# "snippet": "Abraham Lincoln - Facts & Summary - HISTORY ..." -# }, -# ... -# ] -# } +``` + +Which prints: + +```bash +{ + answer="The three major events in the life of Abraham Lincoln are: 1. ...", + sources=[ + { + "name": "HISTORY", + "url": "https://www.history.com/topics/us-presidents/abraham-lincoln", + "snippet": "Abraham Lincoln - Facts & Summary - HISTORY ..." + }, + ... + ] +} ``` Check the code or the @@ -139,11 +143,15 @@ fetch_response: LinkupFetchResponse = client.fetch( include_raw_html=True, ) print(fetch_response.model_dump()) -# Response: -# { -# markdown="Get started for free, no credit card required...", -# raw_html="......" -# } +``` + +Which prints: + +```bash +{ + markdown="Get started for free, no credit card required...", + raw_html="......" +} ``` Check the code or the @@ -175,18 +183,22 @@ async def main() -> None: print(search_response.model_dump()) asyncio.run(main()) -# Response: -# { -# answer="The three major events in the life of Abraham Lincoln are: 1. ...", -# sources=[ -# { -# "name": "HISTORY", -# "url": "https://www.history.com/topics/us-presidents/abraham-lincoln", -# "snippet": "Abraham Lincoln - Facts & Summary - HISTORY ..." -# }, -# ... -# ] -# } +``` + +Which prints: + +```bash +{ + answer="The three major events in the life of Abraham Lincoln are: 1. ...", + sources=[ + { + "name": "HISTORY", + "url": "https://www.history.com/topics/us-presidents/abraham-lincoln", + "snippet": "Abraham Lincoln - Facts & Summary - HISTORY ..." + }, + ... + ] +} ``` #### 📚 More Examples