mirror of
https://github.com/hwchase17/langchain.git
synced 2025-09-11 07:50:47 +00:00
ruff: more rules across the board & fixes (#31898)
* standardizes ruff dep version across all `pyproject.toml` files * cli: ruff rules and corrections * langchain: rules and corrections
This commit is contained in:
@@ -79,7 +79,9 @@ def new(
|
||||
package_prompt = "What package would you like to add? (leave blank to skip)"
|
||||
while True:
|
||||
package_str = typer.prompt(
|
||||
package_prompt, default="", show_default=False
|
||||
package_prompt,
|
||||
default="",
|
||||
show_default=False,
|
||||
)
|
||||
if not package_str:
|
||||
break
|
||||
@@ -121,26 +123,29 @@ def new(
|
||||
typer.echo("Then add templates with commands like:\n")
|
||||
typer.echo(" langchain app add extraction-openai-functions")
|
||||
typer.echo(
|
||||
" langchain app add git+ssh://git@github.com/efriis/simple-pirate.git\n\n"
|
||||
" langchain app add git+ssh://git@github.com/efriis/simple-pirate.git\n\n",
|
||||
)
|
||||
|
||||
|
||||
@app_cli.command()
|
||||
def add(
|
||||
dependencies: Annotated[
|
||||
Optional[list[str]], typer.Argument(help="The dependency to add")
|
||||
Optional[list[str]],
|
||||
typer.Argument(help="The dependency to add"),
|
||||
] = None,
|
||||
*,
|
||||
api_path: Annotated[list[str], typer.Option(help="API paths to add")] = [],
|
||||
project_dir: Annotated[
|
||||
Optional[Path], typer.Option(help="The project directory")
|
||||
Optional[Path],
|
||||
typer.Option(help="The project directory"),
|
||||
] = None,
|
||||
repo: Annotated[
|
||||
list[str],
|
||||
typer.Option(help="Install templates from a specific github repo instead"),
|
||||
] = [],
|
||||
branch: Annotated[
|
||||
list[str], typer.Option(help="Install templates from a specific branch")
|
||||
list[str],
|
||||
typer.Option(help="Install templates from a specific branch"),
|
||||
] = [],
|
||||
pip: Annotated[
|
||||
bool,
|
||||
@@ -152,13 +157,12 @@ def add(
|
||||
),
|
||||
],
|
||||
) -> None:
|
||||
"""Adds the specified template to the current LangServe app.
|
||||
"""Add the specified template to the current LangServe app.
|
||||
|
||||
e.g.:
|
||||
langchain app add extraction-openai-functions
|
||||
langchain app add git+ssh://git@github.com/efriis/simple-pirate.git
|
||||
"""
|
||||
|
||||
if not branch and not repo:
|
||||
warnings.warn(
|
||||
"Adding templates from the default branch and repo is deprecated."
|
||||
@@ -173,7 +177,7 @@ def add(
|
||||
package_dir = project_root / "packages"
|
||||
|
||||
create_events(
|
||||
[{"event": "serve add", "properties": {"parsed_dep": d}} for d in parsed_deps]
|
||||
[{"event": "serve add", "properties": {"parsed_dep": d}} for d in parsed_deps],
|
||||
)
|
||||
|
||||
# group by repo/ref
|
||||
@@ -248,7 +252,7 @@ def add(
|
||||
cmd = ["pip", "install", "-e", *installed_destination_strs]
|
||||
cmd_str = " \\\n ".join(installed_destination_strs)
|
||||
typer.echo(f"Running: pip install -e \\\n {cmd_str}")
|
||||
subprocess.run(cmd, cwd=cwd)
|
||||
subprocess.run(cmd, cwd=cwd) # noqa: S603
|
||||
|
||||
chain_names = []
|
||||
for e in installed_exports:
|
||||
@@ -296,10 +300,11 @@ def remove(
|
||||
api_paths: Annotated[list[str], typer.Argument(help="The API paths to remove")],
|
||||
*,
|
||||
project_dir: Annotated[
|
||||
Optional[Path], typer.Option(help="The project directory")
|
||||
Optional[Path],
|
||||
typer.Option(help="The project directory"),
|
||||
] = None,
|
||||
) -> None:
|
||||
"""Removes the specified package from the current LangServe app."""
|
||||
"""Remove the specified package from the current LangServe app."""
|
||||
project_root = get_package_root(project_dir)
|
||||
|
||||
project_pyproject = project_root / "pyproject.toml"
|
||||
@@ -320,7 +325,7 @@ def remove(
|
||||
|
||||
shutil.rmtree(package_dir)
|
||||
remove_deps.append(api_path)
|
||||
except Exception:
|
||||
except Exception: # noqa: S110
|
||||
pass
|
||||
|
||||
try:
|
||||
@@ -334,16 +339,19 @@ def remove(
|
||||
def serve(
|
||||
*,
|
||||
port: Annotated[
|
||||
Optional[int], typer.Option(help="The port to run the server on")
|
||||
Optional[int],
|
||||
typer.Option(help="The port to run the server on"),
|
||||
] = None,
|
||||
host: Annotated[
|
||||
Optional[str], typer.Option(help="The host to run the server on")
|
||||
Optional[str],
|
||||
typer.Option(help="The host to run the server on"),
|
||||
] = None,
|
||||
app: Annotated[
|
||||
Optional[str], typer.Option(help="The app to run, e.g. `app.server:app`")
|
||||
Optional[str],
|
||||
typer.Option(help="The app to run, e.g. `app.server:app`"),
|
||||
] = None,
|
||||
) -> None:
|
||||
"""Starts the LangServe app."""
|
||||
"""Start the LangServe app."""
|
||||
# add current dir as first entry of path
|
||||
sys.path.append(str(Path.cwd()))
|
||||
|
||||
@@ -353,5 +361,8 @@ def serve(
|
||||
import uvicorn
|
||||
|
||||
uvicorn.run(
|
||||
app_str, host=host_str, port=port if port is not None else 8000, reload=True
|
||||
app_str,
|
||||
host=host_str,
|
||||
port=port if port is not None else 8000,
|
||||
reload=True,
|
||||
)
|
||||
|
@@ -66,7 +66,7 @@ def new(
|
||||
Optional[str],
|
||||
typer.Option(
|
||||
help="The name of the integration in PascalCase. e.g. `MyIntegration`."
|
||||
" This is used to name classes like `MyIntegrationVectorStore`"
|
||||
" This is used to name classes like `MyIntegrationVectorStore`",
|
||||
),
|
||||
] = None,
|
||||
src: Annotated[
|
||||
@@ -85,7 +85,7 @@ def new(
|
||||
),
|
||||
] = None,
|
||||
) -> None:
|
||||
"""Creates a new integration package."""
|
||||
"""Create a new integration package."""
|
||||
try:
|
||||
replacements = _process_name(name)
|
||||
except ValueError as e:
|
||||
@@ -96,13 +96,14 @@ def new(
|
||||
if not re.match(r"^[A-Z][a-zA-Z0-9]*$", name_class):
|
||||
typer.echo(
|
||||
"Name should only contain letters (a-z, A-Z), numbers, and underscores"
|
||||
", and start with a capital letter."
|
||||
", and start with a capital letter.",
|
||||
)
|
||||
raise typer.Exit(code=1)
|
||||
replacements["__ModuleName__"] = name_class
|
||||
else:
|
||||
replacements["__ModuleName__"] = typer.prompt(
|
||||
"Name of integration in PascalCase", default=replacements["__ModuleName__"]
|
||||
"Name of integration in PascalCase",
|
||||
default=replacements["__ModuleName__"],
|
||||
)
|
||||
|
||||
project_template_dir = Path(__file__).parents[1] / "integration_template"
|
||||
@@ -124,7 +125,7 @@ def new(
|
||||
|
||||
# poetry install
|
||||
subprocess.run(
|
||||
["poetry", "install", "--with", "lint,test,typing,test_integration"],
|
||||
["poetry", "install", "--with", "lint,test,typing,test_integration"], # noqa: S607
|
||||
cwd=destination_dir,
|
||||
)
|
||||
else:
|
||||
@@ -152,7 +153,7 @@ def new(
|
||||
if len(dst_paths) != len(set(dst_paths)):
|
||||
typer.echo(
|
||||
"Duplicate destination paths provided or computed - please "
|
||||
"specify them explicitly with --dst."
|
||||
"specify them explicitly with --dst.",
|
||||
)
|
||||
raise typer.Exit(code=1)
|
||||
|
||||
@@ -224,10 +225,10 @@ def create_doc(
|
||||
),
|
||||
] = "docs/docs/integrations/chat/",
|
||||
) -> None:
|
||||
"""Creates a new integration doc."""
|
||||
"""Create a new integration doc."""
|
||||
if component_type not in TEMPLATE_MAP:
|
||||
typer.echo(
|
||||
f"Unrecognized {component_type=}. Expected one of {_component_types_str}."
|
||||
f"Unrecognized {component_type=}. Expected one of {_component_types_str}.",
|
||||
)
|
||||
raise typer.Exit(code=1)
|
||||
|
||||
|
@@ -6,14 +6,17 @@ import pkgutil
|
||||
|
||||
|
||||
def generate_raw_migrations(
|
||||
from_package: str, to_package: str, filter_by_all: bool = False
|
||||
from_package: str,
|
||||
to_package: str,
|
||||
filter_by_all: bool = False, # noqa: FBT001, FBT002
|
||||
) -> list[tuple[str, str]]:
|
||||
"""Scan the `langchain` package and generate migrations for all modules."""
|
||||
package = importlib.import_module(from_package)
|
||||
|
||||
items = []
|
||||
for _importer, modname, _ispkg in pkgutil.walk_packages(
|
||||
package.__path__, package.__name__ + "."
|
||||
package.__path__,
|
||||
package.__name__ + ".",
|
||||
):
|
||||
try:
|
||||
module = importlib.import_module(modname)
|
||||
@@ -34,33 +37,35 @@ def generate_raw_migrations(
|
||||
obj = getattr(module, name, None)
|
||||
except ImportError:
|
||||
continue
|
||||
if obj and (inspect.isclass(obj) or inspect.isfunction(obj)):
|
||||
if obj.__module__.startswith(to_package):
|
||||
items.append(
|
||||
(f"{modname}.{name}", f"{obj.__module__}.{obj.__name__}")
|
||||
)
|
||||
if (
|
||||
obj
|
||||
and (inspect.isclass(obj) or inspect.isfunction(obj))
|
||||
and obj.__module__.startswith(to_package)
|
||||
):
|
||||
items.append(
|
||||
(f"{modname}.{name}", f"{obj.__module__}.{obj.__name__}"),
|
||||
)
|
||||
|
||||
if not filter_by_all:
|
||||
# Iterate over all members of the module
|
||||
for name, obj in inspect.getmembers(module):
|
||||
# Check if it's a class or function
|
||||
if inspect.isclass(obj) or inspect.isfunction(obj):
|
||||
# Check if the module name of the obj starts with
|
||||
# 'langchain_community'
|
||||
if obj.__module__.startswith(to_package):
|
||||
items.append(
|
||||
(f"{modname}.{name}", f"{obj.__module__}.{obj.__name__}")
|
||||
)
|
||||
# Check if the module name of the obj starts with
|
||||
# 'langchain_community'
|
||||
if inspect.isclass(obj) or (
|
||||
inspect.isfunction(obj) and obj.__module__.startswith(to_package)
|
||||
):
|
||||
items.append(
|
||||
(f"{modname}.{name}", f"{obj.__module__}.{obj.__name__}"),
|
||||
)
|
||||
|
||||
return items
|
||||
|
||||
|
||||
def generate_top_level_imports(pkg: str) -> list[tuple[str, str]]:
|
||||
"""This code will look at all the top level modules in langchain_community.
|
||||
"""Look at all the top level modules in langchain_community.
|
||||
|
||||
It'll attempt to import everything from each __init__ file
|
||||
|
||||
for example,
|
||||
Attempt to import everything from each ``__init__`` file. For example,
|
||||
|
||||
langchain_community/
|
||||
chat_models/
|
||||
@@ -74,10 +79,10 @@ def generate_top_level_imports(pkg: str) -> list[tuple[str, str]]:
|
||||
|
||||
Each tuple will contain the fully qualified path of the class / function to where
|
||||
its logic is defined
|
||||
(e.g., langchain_community.chat_models.xyz_implementation.ver2.XYZ)
|
||||
(e.g., ``langchain_community.chat_models.xyz_implementation.ver2.XYZ``)
|
||||
and the second tuple will contain the path
|
||||
to importing it from the top level namespaces
|
||||
(e.g., langchain_community.chat_models.XYZ)
|
||||
(e.g., ``langchain_community.chat_models.XYZ``)
|
||||
"""
|
||||
package = importlib.import_module(pkg)
|
||||
|
||||
@@ -98,7 +103,7 @@ def generate_top_level_imports(pkg: str) -> list[tuple[str, str]]:
|
||||
top_level_import = f"{module_name}.{name}"
|
||||
# Append the tuple with original and top-level paths
|
||||
items.append(
|
||||
(f"{original_module}.{original_name}", top_level_import)
|
||||
(f"{original_module}.{original_name}", top_level_import),
|
||||
)
|
||||
|
||||
# Handle the package itself (root level)
|
||||
@@ -106,7 +111,8 @@ def generate_top_level_imports(pkg: str) -> list[tuple[str, str]]:
|
||||
|
||||
# Only iterate through top-level modules/packages
|
||||
for _finder, modname, ispkg in pkgutil.iter_modules(
|
||||
package.__path__, package.__name__ + "."
|
||||
package.__path__,
|
||||
package.__name__ + ".",
|
||||
):
|
||||
if ispkg:
|
||||
try:
|
||||
@@ -119,11 +125,15 @@ def generate_top_level_imports(pkg: str) -> list[tuple[str, str]]:
|
||||
|
||||
|
||||
def generate_simplified_migrations(
|
||||
from_package: str, to_package: str, filter_by_all: bool = True
|
||||
from_package: str,
|
||||
to_package: str,
|
||||
filter_by_all: bool = True, # noqa: FBT001, FBT002
|
||||
) -> list[tuple[str, str]]:
|
||||
"""Get all the raw migrations, then simplify them if possible."""
|
||||
raw_migrations = generate_raw_migrations(
|
||||
from_package, to_package, filter_by_all=filter_by_all
|
||||
from_package,
|
||||
to_package,
|
||||
filter_by_all=filter_by_all,
|
||||
)
|
||||
top_level_simplifications = generate_top_level_imports(to_package)
|
||||
top_level_dict = dict(top_level_simplifications)
|
||||
|
@@ -17,7 +17,7 @@ def dump_migrations_as_grit(name: str, migration_pairs: list[tuple[str, str]]) -
|
||||
]
|
||||
"""
|
||||
for from_module, to_module in migration_pairs
|
||||
]
|
||||
],
|
||||
)
|
||||
pattern_name = f"langchain_migrate_{name}"
|
||||
return f"""
|
||||
|
@@ -28,6 +28,7 @@ def get_migrations_for_partner_package(pkg_name: str) -> list[tuple[str, str]]:
|
||||
|
||||
Returns:
|
||||
List of 2-tuples containing old and new import paths.
|
||||
|
||||
"""
|
||||
package = importlib.import_module(pkg_name)
|
||||
classes_ = find_subclasses_in_module(
|
||||
|
@@ -20,7 +20,7 @@ class ImportExtractor(ast.NodeVisitor):
|
||||
self.imports: list = []
|
||||
self.package = from_package
|
||||
|
||||
def visit_ImportFrom(self, node) -> None:
|
||||
def visit_ImportFrom(self, node) -> None: # noqa: N802
|
||||
if node.module and (
|
||||
self.package is None or str(node.module).startswith(self.package)
|
||||
):
|
||||
@@ -39,7 +39,7 @@ def _get_class_names(code: str) -> list[str]:
|
||||
|
||||
# Define a node visitor class to collect class names
|
||||
class ClassVisitor(ast.NodeVisitor):
|
||||
def visit_ClassDef(self, node) -> None:
|
||||
def visit_ClassDef(self, node) -> None: # noqa: N802
|
||||
class_names.append(node.name)
|
||||
self.generic_visit(node)
|
||||
|
||||
@@ -79,7 +79,9 @@ def _get_all_classnames_from_file(file: Path, pkg: str) -> list[tuple[str, str]]
|
||||
|
||||
|
||||
def identify_all_imports_in_file(
|
||||
file: str, *, from_package: Optional[str] = None
|
||||
file: str,
|
||||
*,
|
||||
from_package: Optional[str] = None,
|
||||
) -> list[tuple[str, str]]:
|
||||
"""Let's also identify all the imports in the given file."""
|
||||
with open(file, encoding="utf-8") as f:
|
||||
@@ -96,10 +98,13 @@ def identify_pkg_source(pkg_root: str) -> pathlib.Path:
|
||||
|
||||
Returns:
|
||||
Returns the path to the source code for the package.
|
||||
|
||||
"""
|
||||
dirs = [d for d in Path(pkg_root).iterdir() if d.is_dir()]
|
||||
matching_dirs = [d for d in dirs if d.name.startswith("langchain_")]
|
||||
assert len(matching_dirs) == 1, "There should be only one langchain package."
|
||||
if len(matching_dirs) != 1:
|
||||
msg = "There should be only one langchain package."
|
||||
raise ValueError(msg)
|
||||
return matching_dirs[0]
|
||||
|
||||
|
||||
@@ -134,7 +139,9 @@ def list_init_imports_by_package(pkg_root: str) -> list[tuple[str, str]]:
|
||||
|
||||
|
||||
def find_imports_from_package(
|
||||
code: str, *, from_package: Optional[str] = None
|
||||
code: str,
|
||||
*,
|
||||
from_package: Optional[str] = None,
|
||||
) -> list[tuple[str, str]]:
|
||||
# Parse the code into an AST
|
||||
tree = ast.parse(code)
|
||||
|
@@ -4,7 +4,7 @@ from pathlib import Path
|
||||
|
||||
import rich
|
||||
import typer
|
||||
from gritql import run # type: ignore
|
||||
from gritql import run # type: ignore[import]
|
||||
from typer import Option
|
||||
|
||||
|
||||
@@ -17,13 +17,13 @@ def get_gritdir_path() -> Path:
|
||||
def migrate(
|
||||
ctx: typer.Context,
|
||||
# Using diff instead of dry-run for backwards compatibility with the old CLI
|
||||
diff: bool = Option(
|
||||
False,
|
||||
diff: bool = Option( # noqa: FBT001
|
||||
False, # noqa: FBT003
|
||||
"--diff",
|
||||
help="Show the changes that would be made without applying them.",
|
||||
),
|
||||
interactive: bool = Option(
|
||||
False,
|
||||
interactive: bool = Option( # noqa: FBT001
|
||||
False, # noqa: FBT003
|
||||
"--interactive",
|
||||
help="Prompt for confirmation before making each change",
|
||||
),
|
||||
@@ -54,7 +54,7 @@ def migrate(
|
||||
'⚠️ This script is a "best-effort", and is likely to make some '
|
||||
"mistakes.\n\n"
|
||||
"🛡️ Backup your code prior to running the migration script -- it will "
|
||||
"modify your files!\n\n"
|
||||
"modify your files!\n\n",
|
||||
)
|
||||
rich.print("-" * 10)
|
||||
rich.print()
|
||||
|
@@ -16,12 +16,12 @@ package_cli = typer.Typer(no_args_is_help=True, add_completion=False)
|
||||
@package_cli.command()
|
||||
def new(
|
||||
name: Annotated[str, typer.Argument(help="The name of the folder to create")],
|
||||
with_poetry: Annotated[
|
||||
with_poetry: Annotated[ # noqa: FBT002
|
||||
bool,
|
||||
typer.Option("--with-poetry/--no-poetry", help="Don't run poetry install"),
|
||||
] = False,
|
||||
) -> None:
|
||||
"""Creates a new template package."""
|
||||
"""Create a new template package."""
|
||||
computed_name = name if name != "." else Path.cwd().name
|
||||
destination_dir = Path.cwd() / name if name != "." else Path.cwd()
|
||||
|
||||
@@ -53,8 +53,9 @@ def new(
|
||||
pyproject_contents = pyproject.read_text()
|
||||
pyproject.write_text(
|
||||
pyproject_contents.replace("__package_name__", package_name).replace(
|
||||
"__module_name__", module_name
|
||||
)
|
||||
"__module_name__",
|
||||
module_name,
|
||||
),
|
||||
)
|
||||
|
||||
# move module folder
|
||||
@@ -71,23 +72,26 @@ def new(
|
||||
readme_contents = readme.read_text()
|
||||
readme.write_text(
|
||||
readme_contents.replace("__package_name__", package_name).replace(
|
||||
"__app_route_code__", app_route_code
|
||||
)
|
||||
"__app_route_code__",
|
||||
app_route_code,
|
||||
),
|
||||
)
|
||||
|
||||
# poetry install
|
||||
if with_poetry:
|
||||
subprocess.run(["poetry", "install"], cwd=destination_dir)
|
||||
subprocess.run(["poetry", "install"], cwd=destination_dir) # noqa: S607
|
||||
|
||||
|
||||
@package_cli.command()
|
||||
def serve(
|
||||
*,
|
||||
port: Annotated[
|
||||
Optional[int], typer.Option(help="The port to run the server on")
|
||||
Optional[int],
|
||||
typer.Option(help="The port to run the server on"),
|
||||
] = None,
|
||||
host: Annotated[
|
||||
Optional[str], typer.Option(help="The host to run the server on")
|
||||
Optional[str],
|
||||
typer.Option(help="The host to run the server on"),
|
||||
] = None,
|
||||
configurable: Annotated[
|
||||
Optional[bool],
|
||||
@@ -104,7 +108,7 @@ def serve(
|
||||
),
|
||||
] = False,
|
||||
) -> None:
|
||||
"""Starts a demo app for this template."""
|
||||
"""Start a demo app for this template."""
|
||||
# load pyproject.toml
|
||||
project_dir = get_package_root()
|
||||
pyproject = project_dir / "pyproject.toml"
|
||||
@@ -136,7 +140,7 @@ def serve(
|
||||
|
||||
|
||||
@package_cli.command()
|
||||
def list(contains: Annotated[Optional[str], typer.Argument()] = None) -> None:
|
||||
def list(contains: Annotated[Optional[str], typer.Argument()] = None) -> None: # noqa: A001
|
||||
"""List all or search for available templates."""
|
||||
from langchain_cli.utils.github import list_packages
|
||||
|
||||
|
Reference in New Issue
Block a user