core[patch]: Add ruff rules for PLW (Pylint Warnings) (#29288)

See https://docs.astral.sh/ruff/rules/#warning-w_1

---------

Co-authored-by: Eugene Yurtsev <eyurtsev@gmail.com>
This commit is contained in:
Christophe Bornet 2025-03-27 11:26:12 +01:00 committed by GitHub
parent 75823d580b
commit b28a474e79
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 43 additions and 32 deletions

View File

@ -504,7 +504,7 @@ def filter_messages(
)
]
msg = msg.model_copy(
msg = msg.model_copy( # noqa: PLW2901
update={"tool_calls": tool_calls, "content": content}
)
elif (

View File

@ -125,5 +125,11 @@ class JsonOutputParser(BaseCumulativeTransformOutputParser[Any]):
# For backwards compatibility
SimpleJsonOutputParser = JsonOutputParser
parse_partial_json = parse_partial_json
parse_and_check_json_markdown = parse_and_check_json_markdown
__all__ = [
"JsonOutputParser",
"SimpleJsonOutputParser", # For backwards compatibility
"parse_partial_json", # For backwards compatibility
"parse_and_check_json_markdown", # For backwards compatibility
]

View File

@ -73,9 +73,10 @@ class ListOutputParser(BaseTransformOutputParser[list[str]]):
chunk_content = chunk.content
if not isinstance(chunk_content, str):
continue
chunk = chunk_content
# add current chunk to buffer
buffer += chunk
buffer += chunk_content
else:
# add current chunk to buffer
buffer += chunk
# parse buffer into a list of parts
try:
done_idx = 0
@ -105,9 +106,10 @@ class ListOutputParser(BaseTransformOutputParser[list[str]]):
chunk_content = chunk.content
if not isinstance(chunk_content, str):
continue
chunk = chunk_content
# add current chunk to buffer
buffer += chunk
buffer += chunk_content
else:
# add current chunk to buffer
buffer += chunk
# parse buffer into a list of parts
try:
done_idx = 0

View File

@ -29,7 +29,6 @@ _TRACERS: weakref.WeakSet[EvaluatorCallbackHandler] = weakref.WeakSet()
def wait_for_all_evaluators() -> None:
"""Wait for all tracers to finish."""
global _TRACERS
for tracer in list(_TRACERS):
if tracer is not None:
tracer.wait_for_futures()
@ -100,7 +99,6 @@ class EvaluatorCallbackHandler(BaseTracer):
self.project_name = project_name
self.logged_eval_results: dict[tuple[str, str], list[EvaluationResult]] = {}
self.lock = threading.Lock()
global _TRACERS
_TRACERS.add(self)
def _evaluate_in_project(self, run: Run, evaluator: langsmith.RunEvaluator) -> None:

View File

@ -41,7 +41,6 @@ def log_error_once(method: str, exception: Exception) -> None:
method: The method that raised the exception.
exception: The exception that was raised.
"""
global _LOGGED
if (method, type(exception)) in _LOGGED:
return
_LOGGED.add((method, type(exception)))
@ -61,7 +60,7 @@ def get_client() -> Client:
def _get_executor() -> ThreadPoolExecutor:
"""Get the executor."""
global _EXECUTOR
global _EXECUTOR # noqa: PLW0603
if _EXECUTOR is None:
_EXECUTOR = ThreadPoolExecutor()
return _EXECUTOR

View File

@ -96,9 +96,12 @@ def merge_lists(left: Optional[list], *others: Optional[list]) -> Optional[list]
if to_merge:
# TODO: Remove this once merge_dict is updated with special
# handling for 'type'.
if "type" in e:
e = {k: v for k, v in e.items() if k != "type"}
merged[to_merge[0]] = merge_dicts(merged[to_merge[0]], e)
new_e = (
{k: v for k, v in e.items() if k != "type"}
if "type" in e
else e
)
merged[to_merge[0]] = merge_dicts(merged[to_merge[0]], new_e)
else:
merged.append(e)
else:

View File

@ -64,11 +64,14 @@ def parse_partial_json(s: str, *, strict: bool = False) -> Any:
# Process each character in the string one at a time.
for char in s:
new_char = char
if is_inside_string:
if char == '"' and not escaped:
is_inside_string = False
elif char == "\n" and not escaped:
char = "\\n" # Replace the newline character with the escape sequence.
new_char = (
"\\n" # Replace the newline character with the escape sequence.
)
elif char == "\\":
escaped = not escaped
else:
@ -89,7 +92,7 @@ def parse_partial_json(s: str, *, strict: bool = False) -> Any:
return None
# Append the processed character to the new string.
new_chars.append(char)
new_chars.append(new_char)
# If we're still inside a string at the end of processing,
# we need to close the string.

View File

@ -125,8 +125,6 @@ def parse_tag(template: str, l_del: str, r_del: str) -> tuple[tuple[str, str], s
ChevronError: If the tag is unclosed.
ChevronError: If the set delimiter tag is unclosed.
"""
global _CURRENT_LINE, _LAST_TAG_LINE
tag_types = {
"!": "comment",
"#": "section",
@ -352,32 +350,33 @@ def _get_key(
if scope in (0, False):
return scope
resolved_scope = scope
# For every dot separated key
for child in key.split("."):
# Return an empty string if falsy, with two exceptions
# 0 should return 0, and False should return False
if scope in (0, False):
return scope
if resolved_scope in (0, False):
return resolved_scope
# Move into the scope
try:
# Try subscripting (Normal dictionaries)
scope = cast(dict[str, Any], scope)[child]
resolved_scope = cast(dict[str, Any], resolved_scope)[child]
except (TypeError, AttributeError):
try:
scope = getattr(scope, child)
resolved_scope = getattr(resolved_scope, child)
except (TypeError, AttributeError):
# Try as a list
scope = scope[int(child)] # type: ignore
resolved_scope = resolved_scope[int(child)] # type: ignore
try:
# This allows for custom falsy data types
# https://github.com/noahmorrison/chevron/issues/35
if scope._CHEVRON_return_scope_when_falsy: # type: ignore
return scope
if resolved_scope._CHEVRON_return_scope_when_falsy: # type: ignore
return resolved_scope
except AttributeError:
if scope in (0, False):
return scope
return scope or ""
if resolved_scope in (0, False):
return resolved_scope
return resolved_scope or ""
except (AttributeError, KeyError, IndexError, ValueError):
# We couldn't find the key in the current scope
# We'll try again on the next pass

View File

@ -77,7 +77,7 @@ target-version = "py39"
[tool.ruff.lint]
select = [ "ANN", "ASYNC", "B", "C4", "COM", "DJ", "E", "EM", "EXE", "F", "FLY", "FURB", "I", "ICN", "INT", "LOG", "N", "NPY", "PD", "PIE", "PTH", "Q", "RSE", "S", "SIM", "SLOT", "T10", "T201", "TC", "TID", "TRY", "UP", "W", "YTT",]
select = [ "ANN", "ASYNC", "B", "C4", "COM", "DJ", "E", "EM", "EXE", "F", "FLY", "FURB", "I", "ICN", "INT", "LOG", "N", "NPY", "PD", "PIE", "PLW", "PTH", "Q", "RSE", "S", "SIM", "SLOT", "T10", "T201", "TC", "TID", "TRY", "UP", "W", "YTT",]
ignore = [ "ANN401", "COM812", "UP007", "S110", "S112", "TC001", "TC002", "TC003"]
flake8-type-checking.runtime-evaluated-base-classes = ["pydantic.BaseModel","langchain_core.load.serializable.Serializable","langchain_core.runnables.base.RunnableSerializable"]
flake8-annotations.allow-star-arg-any = true
@ -96,6 +96,7 @@ filterwarnings = [ "ignore::langchain_core._api.beta_decorator.LangChainBetaWarn
classmethod-decorators = [ "classmethod", "langchain_core.utils.pydantic.pre_init", "pydantic.field_validator", "pydantic.v1.root_validator",]
[tool.ruff.lint.per-file-ignores]
"langchain_core/utils/mustache.py" = [ "PLW0603",]
"tests/unit_tests/prompts/test_chat.py" = [ "E501",]
"tests/unit_tests/runnables/test_runnable.py" = [ "E501",]
"tests/unit_tests/runnables/test_graph.py" = [ "E501",]

View File

@ -22,7 +22,7 @@ def try_to_import(module_name: str) -> tuple[int, str]:
getattr(module, cls_)
result = subprocess.run(
["python", "-c", f"import langchain_core.{module_name}"],
["python", "-c", f"import langchain_core.{module_name}"], check=True
)
return result.returncode, module_name