diff --git a/libs/partners/exa/langchain_exa/__init__.py b/libs/partners/exa/langchain_exa/__init__.py index 6bced9e261b..552a836a5e6 100644 --- a/libs/partners/exa/langchain_exa/__init__.py +++ b/libs/partners/exa/langchain_exa/__init__.py @@ -1,4 +1,4 @@ -from exa_py.api import ( # type: ignore # type: ignore[import-not-found, import-not-found] +from exa_py.api import ( HighlightsContentsOptions, TextContentsOptions, ) @@ -7,9 +7,9 @@ from langchain_exa.retrievers import ExaSearchRetriever from langchain_exa.tools import ExaFindSimilarResults, ExaSearchResults __all__ = [ + "ExaFindSimilarResults", "ExaSearchResults", "ExaSearchRetriever", "HighlightsContentsOptions", "TextContentsOptions", - "ExaFindSimilarResults", ] diff --git a/libs/partners/exa/langchain_exa/_utilities.py b/libs/partners/exa/langchain_exa/_utilities.py index 5e0dac692aa..14e8e82e29f 100644 --- a/libs/partners/exa/langchain_exa/_utilities.py +++ b/libs/partners/exa/langchain_exa/_utilities.py @@ -1,6 +1,6 @@ import os # type: ignore[import-not-found] -from exa_py import Exa # type: ignore +from exa_py import Exa from langchain_core.utils import convert_to_secret_str diff --git a/libs/partners/exa/langchain_exa/retrievers.py b/libs/partners/exa/langchain_exa/retrievers.py index 08b9b450fc8..cce2f68f186 100644 --- a/libs/partners/exa/langchain_exa/retrievers.py +++ b/libs/partners/exa/langchain_exa/retrievers.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import Any, Literal, Optional, Union from exa_py import Exa # type: ignore[untyped-import] @@ -75,17 +77,16 @@ class ExaSearchRetriever(BaseRetriever): @classmethod def validate_environment(cls, values: dict) -> Any: """Validate the environment.""" - values = initialize_client(values) - return values + return initialize_client(values) def _get_relevant_documents( self, query: str, *, run_manager: CallbackManagerForRetrieverRun ) -> list[Document]: - response = self.client.search_and_contents( # type: ignore[misc] + response = self.client.search_and_contents( # type: ignore[call-overload] query, num_results=self.k, text=self.text_contents_options, - highlights=self.highlights, # type: ignore + highlights=self.highlights, include_domains=self.include_domains, exclude_domains=self.exclude_domains, start_crawl_date=self.start_crawl_date, @@ -96,7 +97,7 @@ class ExaSearchRetriever(BaseRetriever): livecrawl=self.livecrawl, summary=self.summary, type=self.type, - ) + ) # type: ignore[call-overload, misc] results = response.results diff --git a/libs/partners/exa/langchain_exa/tools.py b/libs/partners/exa/langchain_exa/tools.py index 381dade1c53..4ecfdad2c78 100644 --- a/libs/partners/exa/langchain_exa/tools.py +++ b/libs/partners/exa/langchain_exa/tools.py @@ -1,5 +1,7 @@ """Tool for the Exa Search API.""" +from __future__ import annotations + from typing import Any, Literal, Optional, Union from exa_py import Exa # type: ignore[untyped-import] @@ -17,7 +19,7 @@ from langchain_exa._utilities import initialize_client class ExaSearchResults(BaseTool): # type: ignore[override] - """Exa Search tool. + r"""Exa Search tool. Setup: Install ``langchain-exa`` and set environment variable ``EXA_API_KEY``. @@ -68,8 +70,7 @@ class ExaSearchResults(BaseTool): # type: ignore[override] @classmethod def validate_environment(cls, values: dict) -> Any: """Validate the environment.""" - values = initialize_client(values) - return values + return initialize_client(values) def _run( self, @@ -88,9 +89,10 @@ class ExaSearchResults(BaseTool): # type: ignore[override] use_autoprompt: Optional[bool] = None, livecrawl: Optional[Literal["always", "fallback", "never"]] = None, summary: Optional[Union[bool, dict[str, str]]] = None, - type: Optional[Literal["neural", "keyword", "auto"]] = None, + type: Optional[Literal["neural", "keyword", "auto"]] = None, # noqa: A002 run_manager: Optional[CallbackManagerForToolRun] = None, ) -> Union[list[dict], str]: + # TODO: rename `type` to something else, as it is a reserved keyword """Use the tool. Args: @@ -109,13 +111,14 @@ class ExaSearchResults(BaseTool): # type: ignore[override] summary: Whether to include a summary of the content. Can be a boolean or a dict with a custom query. type: The type of search, 'keyword', 'neural', or 'auto'. run_manager: The run manager for callbacks. + """ # noqa: E501 try: return self.client.search_and_contents( query, num_results=num_results, - text=text_contents_options, # type: ignore - highlights=highlights, # type: ignore + text=text_contents_options, + highlights=highlights, include_domains=include_domains, exclude_domains=exclude_domains, start_crawl_date=start_crawl_date, @@ -126,7 +129,7 @@ class ExaSearchResults(BaseTool): # type: ignore[override] livecrawl=livecrawl, summary=summary, type=type, - ) # type: ignore + ) # type: ignore[call-overload, misc] except Exception as e: return repr(e) @@ -148,8 +151,7 @@ class ExaFindSimilarResults(BaseTool): # type: ignore[override] @classmethod def validate_environment(cls, values: dict) -> Any: """Validate the environment.""" - values = initialize_client(values) - return values + return initialize_client(values) def _run( self, @@ -189,13 +191,14 @@ class ExaFindSimilarResults(BaseTool): # type: ignore[override] livecrawl: Option to crawl live webpages if content is not in the index. Options: "always", "fallback", "never" summary: Whether to include a summary of the content. Can be a boolean or a dict with a custom query. run_manager: The run manager for callbacks. + """ # noqa: E501 try: return self.client.find_similar_and_contents( url, num_results=num_results, - text=text_contents_options, # type: ignore - highlights=highlights, # type: ignore + text=text_contents_options, + highlights=highlights, include_domains=include_domains, exclude_domains=exclude_domains, start_crawl_date=start_crawl_date, @@ -206,6 +209,6 @@ class ExaFindSimilarResults(BaseTool): # type: ignore[override] category=category, livecrawl=livecrawl, summary=summary, - ) # type: ignore + ) # type: ignore[call-overload, misc] except Exception as e: return repr(e) diff --git a/libs/partners/exa/pyproject.toml b/libs/partners/exa/pyproject.toml index 9dda05d792f..80d87e5be4a 100644 --- a/libs/partners/exa/pyproject.toml +++ b/libs/partners/exa/pyproject.toml @@ -48,8 +48,58 @@ disallow_untyped_defs = "True" target-version = "py39" [tool.ruff.lint] -select = ["E", "F", "I", "T201", "UP", "S"] -ignore = [ "UP007", ] +select = [ + "A", # flake8-builtins + "ASYNC", # flake8-async + "C4", # flake8-comprehensions + "COM", # flake8-commas + "D", # pydocstyle + "DOC", # pydoclint + "E", # pycodestyle error + "EM", # flake8-errmsg + "F", # pyflakes + "FA", # flake8-future-annotations + "FBT", # flake8-boolean-trap + "FLY", # flake8-flynt + "I", # isort + "ICN", # flake8-import-conventions + "INT", # flake8-gettext + "ISC", # isort-comprehensions + "PGH", # pygrep-hooks + "PIE", # flake8-pie + "PERF", # flake8-perf + "PYI", # flake8-pyi + "Q", # flake8-quotes + "RET", # flake8-return + "RSE", # flake8-rst-docstrings + "RUF", # ruff + "S", # flake8-bandit + "SLF", # flake8-self + "SLOT", # flake8-slots + "SIM", # flake8-simplify + "T10", # flake8-debugger + "T20", # flake8-print + "TID", # flake8-tidy-imports + "UP", # pyupgrade + "W", # pycodestyle warning + "YTT", # flake8-2020 +] +ignore = [ + "D100", # Missing docstring in public module + "D101", # Missing docstring in public class + "D102", # Missing docstring in public method + "D103", # Missing docstring in public function + "D104", # Missing docstring in public package + "D105", # Missing docstring in magic method + "D107", # Missing docstring in __init__ + "COM812", # Messes with the formatter + "ISC001", # Messes with the formatter + "PERF203", # Rarely useful + "S112", # Rarely useful + "RUF012", # Doesn't play well with Pydantic + "SLF001", # Private member access + "UP007", # pyupgrade: non-pep604-annotation-union +] [tool.coverage.run] omit = ["tests/*"] diff --git a/libs/partners/exa/tests/integration_tests/test_compile.py b/libs/partners/exa/tests/integration_tests/test_compile.py index c2f45e44700..e44fac59a0f 100644 --- a/libs/partners/exa/tests/integration_tests/test_compile.py +++ b/libs/partners/exa/tests/integration_tests/test_compile.py @@ -4,4 +4,3 @@ import pytest # type: ignore[import-not-found, import-not-found] @pytest.mark.compile def test_placeholder() -> None: """Used for compiling integration tests without running any real tests.""" - pass