exa[patch]: ruff fixes and rules (#31902)

* bump ruff deps
* add more thorough ruff rules
* fix said rules
This commit is contained in:
Mason Daugherty 2025-07-07 22:02:42 -04:00 committed by GitHub
parent 231e8d0f43
commit 63e3f2dea6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 76 additions and 23 deletions

View File

@ -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, HighlightsContentsOptions,
TextContentsOptions, TextContentsOptions,
) )
@ -7,9 +7,9 @@ from langchain_exa.retrievers import ExaSearchRetriever
from langchain_exa.tools import ExaFindSimilarResults, ExaSearchResults from langchain_exa.tools import ExaFindSimilarResults, ExaSearchResults
__all__ = [ __all__ = [
"ExaFindSimilarResults",
"ExaSearchResults", "ExaSearchResults",
"ExaSearchRetriever", "ExaSearchRetriever",
"HighlightsContentsOptions", "HighlightsContentsOptions",
"TextContentsOptions", "TextContentsOptions",
"ExaFindSimilarResults",
] ]

View File

@ -1,6 +1,6 @@
import os # type: ignore[import-not-found] 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 from langchain_core.utils import convert_to_secret_str

View File

@ -1,3 +1,5 @@
from __future__ import annotations
from typing import Any, Literal, Optional, Union from typing import Any, Literal, Optional, Union
from exa_py import Exa # type: ignore[untyped-import] from exa_py import Exa # type: ignore[untyped-import]
@ -75,17 +77,16 @@ class ExaSearchRetriever(BaseRetriever):
@classmethod @classmethod
def validate_environment(cls, values: dict) -> Any: def validate_environment(cls, values: dict) -> Any:
"""Validate the environment.""" """Validate the environment."""
values = initialize_client(values) return initialize_client(values)
return values
def _get_relevant_documents( def _get_relevant_documents(
self, query: str, *, run_manager: CallbackManagerForRetrieverRun self, query: str, *, run_manager: CallbackManagerForRetrieverRun
) -> list[Document]: ) -> list[Document]:
response = self.client.search_and_contents( # type: ignore[misc] response = self.client.search_and_contents( # type: ignore[call-overload]
query, query,
num_results=self.k, num_results=self.k,
text=self.text_contents_options, text=self.text_contents_options,
highlights=self.highlights, # type: ignore highlights=self.highlights,
include_domains=self.include_domains, include_domains=self.include_domains,
exclude_domains=self.exclude_domains, exclude_domains=self.exclude_domains,
start_crawl_date=self.start_crawl_date, start_crawl_date=self.start_crawl_date,
@ -96,7 +97,7 @@ class ExaSearchRetriever(BaseRetriever):
livecrawl=self.livecrawl, livecrawl=self.livecrawl,
summary=self.summary, summary=self.summary,
type=self.type, type=self.type,
) ) # type: ignore[call-overload, misc]
results = response.results results = response.results

View File

@ -1,5 +1,7 @@
"""Tool for the Exa Search API.""" """Tool for the Exa Search API."""
from __future__ import annotations
from typing import Any, Literal, Optional, Union from typing import Any, Literal, Optional, Union
from exa_py import Exa # type: ignore[untyped-import] 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] class ExaSearchResults(BaseTool): # type: ignore[override]
"""Exa Search tool. r"""Exa Search tool.
Setup: Setup:
Install ``langchain-exa`` and set environment variable ``EXA_API_KEY``. Install ``langchain-exa`` and set environment variable ``EXA_API_KEY``.
@ -68,8 +70,7 @@ class ExaSearchResults(BaseTool): # type: ignore[override]
@classmethod @classmethod
def validate_environment(cls, values: dict) -> Any: def validate_environment(cls, values: dict) -> Any:
"""Validate the environment.""" """Validate the environment."""
values = initialize_client(values) return initialize_client(values)
return values
def _run( def _run(
self, self,
@ -88,9 +89,10 @@ class ExaSearchResults(BaseTool): # type: ignore[override]
use_autoprompt: Optional[bool] = None, use_autoprompt: Optional[bool] = None,
livecrawl: Optional[Literal["always", "fallback", "never"]] = None, livecrawl: Optional[Literal["always", "fallback", "never"]] = None,
summary: Optional[Union[bool, dict[str, str]]] = 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, run_manager: Optional[CallbackManagerForToolRun] = None,
) -> Union[list[dict], str]: ) -> Union[list[dict], str]:
# TODO: rename `type` to something else, as it is a reserved keyword
"""Use the tool. """Use the tool.
Args: 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. 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'. type: The type of search, 'keyword', 'neural', or 'auto'.
run_manager: The run manager for callbacks. run_manager: The run manager for callbacks.
""" # noqa: E501 """ # noqa: E501
try: try:
return self.client.search_and_contents( return self.client.search_and_contents(
query, query,
num_results=num_results, num_results=num_results,
text=text_contents_options, # type: ignore text=text_contents_options,
highlights=highlights, # type: ignore highlights=highlights,
include_domains=include_domains, include_domains=include_domains,
exclude_domains=exclude_domains, exclude_domains=exclude_domains,
start_crawl_date=start_crawl_date, start_crawl_date=start_crawl_date,
@ -126,7 +129,7 @@ class ExaSearchResults(BaseTool): # type: ignore[override]
livecrawl=livecrawl, livecrawl=livecrawl,
summary=summary, summary=summary,
type=type, type=type,
) # type: ignore ) # type: ignore[call-overload, misc]
except Exception as e: except Exception as e:
return repr(e) return repr(e)
@ -148,8 +151,7 @@ class ExaFindSimilarResults(BaseTool): # type: ignore[override]
@classmethod @classmethod
def validate_environment(cls, values: dict) -> Any: def validate_environment(cls, values: dict) -> Any:
"""Validate the environment.""" """Validate the environment."""
values = initialize_client(values) return initialize_client(values)
return values
def _run( def _run(
self, 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" 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. 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. run_manager: The run manager for callbacks.
""" # noqa: E501 """ # noqa: E501
try: try:
return self.client.find_similar_and_contents( return self.client.find_similar_and_contents(
url, url,
num_results=num_results, num_results=num_results,
text=text_contents_options, # type: ignore text=text_contents_options,
highlights=highlights, # type: ignore highlights=highlights,
include_domains=include_domains, include_domains=include_domains,
exclude_domains=exclude_domains, exclude_domains=exclude_domains,
start_crawl_date=start_crawl_date, start_crawl_date=start_crawl_date,
@ -206,6 +209,6 @@ class ExaFindSimilarResults(BaseTool): # type: ignore[override]
category=category, category=category,
livecrawl=livecrawl, livecrawl=livecrawl,
summary=summary, summary=summary,
) # type: ignore ) # type: ignore[call-overload, misc]
except Exception as e: except Exception as e:
return repr(e) return repr(e)

View File

@ -48,8 +48,58 @@ disallow_untyped_defs = "True"
target-version = "py39" target-version = "py39"
[tool.ruff.lint] [tool.ruff.lint]
select = ["E", "F", "I", "T201", "UP", "S"] select = [
ignore = [ "UP007", ] "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] [tool.coverage.run]
omit = ["tests/*"] omit = ["tests/*"]

View File

@ -4,4 +4,3 @@ import pytest # type: ignore[import-not-found, import-not-found]
@pytest.mark.compile @pytest.mark.compile
def test_placeholder() -> None: def test_placeholder() -> None:
"""Used for compiling integration tests without running any real tests.""" """Used for compiling integration tests without running any real tests."""
pass