Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions libs/core/langchain_core/output_parsers/json.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
from langchain_core.output_parsers.transform import BaseCumulativeTransformOutputParser
from langchain_core.outputs import Generation
from langchain_core.utils.json import (
parse_and_check_json_markdown,
parse_and_check_json_markdown, # noqa: F401 backward compatibility
parse_json_markdown,
parse_partial_json,
parse_partial_json, # noqa: F401 backward compatibility
)
from langchain_core.utils.pydantic import PYDANTIC_MAJOR_VERSION

Expand Down Expand Up @@ -125,5 +125,3 @@ def _type(self) -> str:

# For backwards compatibility
SimpleJsonOutputParser = JsonOutputParser
parse_partial_json = parse_partial_json
parse_and_check_json_markdown = parse_and_check_json_markdown
14 changes: 8 additions & 6 deletions libs/core/langchain_core/output_parsers/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,10 @@ def _transform(
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
Expand Down Expand Up @@ -103,9 +104,10 @@ async def _atransform(
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
Expand Down
2 changes: 0 additions & 2 deletions libs/core/langchain_core/tracers/evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@

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()
Expand Down Expand Up @@ -99,7 +98,6 @@ def __init__(
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:
Expand Down
3 changes: 1 addition & 2 deletions libs/core/langchain_core/tracers/langchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,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)))
Expand All @@ -62,7 +61,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
Expand Down
9 changes: 6 additions & 3 deletions libs/core/langchain_core/utils/_merge.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
others = (
{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]], others)
else:
merged.append(e)
else:
Expand Down
7 changes: 5 additions & 2 deletions libs/core/langchain_core/utils/json.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,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:
Expand All @@ -90,7 +93,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.
Expand Down
24 changes: 11 additions & 13 deletions libs/core/langchain_core/utils/mustache.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,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
global _LAST_TAG_LINE

tag_types = {
"!": "comment",
"#": "section",
Expand Down Expand Up @@ -367,32 +364,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
Expand Down
3 changes: 2 additions & 1 deletion libs/core/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ python = ">=3.12.4"
[tool.poetry.extras]

[tool.ruff.lint]
select = [ "ASYNC", "B", "C4", "COM", "DJ", "E", "EM", "EXE", "F", "FLY", "FURB", "I", "ICN", "INT", "LOG", "N", "NPY", "PD", "PIE", "Q", "RSE", "S", "SIM", "SLOT", "T10", "T201", "TID", "UP", "W", "YTT",]
select = [ "ASYNC", "B", "C4", "COM", "DJ", "E", "EM", "EXE", "F", "FLY", "FURB", "I", "ICN", "INT", "LOG", "N", "NPY", "PD", "PIE", "PLW", "Q", "RSE", "S", "SIM", "SLOT", "T10", "T201", "TID", "UP", "W", "YTT",]
ignore = [ "COM812", "UP007", "W293", "S101", "S110", "S112",]

[tool.coverage.run]
Expand Down Expand Up @@ -75,6 +75,7 @@ optional = true
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",]
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this rule could be ignored completely ?

"tests/unit_tests/prompts/test_chat.py" = [ "E501",]
"tests/unit_tests/runnables/test_runnable.py" = [ "E501",]
"tests/unit_tests/runnables/test_graph.py" = [ "E501",]
Expand Down
2 changes: 1 addition & 1 deletion libs/core/tests/unit_tests/test_imports.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,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

Expand Down
Loading