ref: Add ruff rules for bandit (S) (#4111)
* Add ruff rules for bandit (S) * Changes following review
This commit is contained in:
parent
6180a6daed
commit
8224bce532
28 changed files with 455 additions and 41 deletions
|
|
@ -24,7 +24,7 @@ def get_patched_openai_client(shared_component_cache):
|
|||
|
||||
|
||||
url = "https://raw.githubusercontent.com/BerriAI/litellm/refs/heads/main/model_prices_and_context_window.json"
|
||||
response = requests.get(url)
|
||||
response = requests.get(url, timeout=10)
|
||||
data = json.loads(response.text)
|
||||
|
||||
# Extract the model names into a Python list
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ def normalize_newlines(multiline_text):
|
|||
|
||||
def parse_curl_command(curl_command):
|
||||
tokens = shlex.split(normalize_newlines(curl_command))
|
||||
tokens = [token for token in tokens if token and token != " "]
|
||||
tokens = [token for token in tokens if token and token != " "] # noqa: S105
|
||||
if tokens and "curl" not in tokens[0]:
|
||||
msg = "Invalid curl command"
|
||||
raise ValueError(msg)
|
||||
|
|
@ -78,7 +78,7 @@ def parse_curl_command(curl_command):
|
|||
i = 0
|
||||
while i < len(tokens):
|
||||
token = tokens[i]
|
||||
if token == "-X":
|
||||
if token == "-X": # noqa: S105
|
||||
i += 1
|
||||
args["method"] = tokens[i].lower()
|
||||
method_on_curl = tokens[i].lower()
|
||||
|
|
@ -91,7 +91,7 @@ def parse_curl_command(curl_command):
|
|||
elif token in {"-H", "--header"}:
|
||||
i += 1
|
||||
args["headers"].append(tokens[i])
|
||||
elif token == "--compressed":
|
||||
elif token == "--compressed": # noqa: S105
|
||||
args["compressed"] = True
|
||||
elif token in {"-k", "--insecure"}:
|
||||
args["insecure"] = True
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import unicodedata
|
||||
import xml.etree.ElementTree as ET
|
||||
from collections.abc import Callable
|
||||
from concurrent import futures
|
||||
from pathlib import Path
|
||||
|
|
@ -7,6 +6,7 @@ from pathlib import Path
|
|||
import chardet
|
||||
import orjson
|
||||
import yaml
|
||||
from defusedxml import ElementTree
|
||||
|
||||
from langflow.schema import Data
|
||||
|
||||
|
|
@ -155,8 +155,8 @@ def parse_text_file_to_data(file_path: str, *, silent_errors: bool) -> Data | No
|
|||
elif file_path.endswith((".yaml", ".yml")):
|
||||
text = yaml.safe_load(text)
|
||||
elif file_path.endswith(".xml"):
|
||||
xml_element = ET.fromstring(text)
|
||||
text = ET.tostring(xml_element, encoding="unicode")
|
||||
xml_element = ElementTree.fromstring(text)
|
||||
text = ElementTree.tostring(xml_element, encoding="unicode")
|
||||
except Exception as e:
|
||||
if not silent_errors:
|
||||
msg = f"Error loading file {file_path}: {e}"
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ class AddContentToPage(LCToolComponent):
|
|||
"children": blocks,
|
||||
}
|
||||
|
||||
response = requests.patch(url, headers=headers, json=data)
|
||||
response = requests.patch(url, headers=headers, json=data, timeout=10)
|
||||
response.raise_for_status()
|
||||
|
||||
return response.json()
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ class NotionPageCreator(LCToolComponent):
|
|||
}
|
||||
|
||||
try:
|
||||
response = requests.post("https://api.notion.com/v1/pages", headers=headers, json=data)
|
||||
response = requests.post("https://api.notion.com/v1/pages", headers=headers, json=data, timeout=10)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
except requests.exceptions.RequestException as e:
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ class NotionDatabaseProperties(LCToolComponent):
|
|||
"Notion-Version": "2022-06-28", # Use the latest supported version
|
||||
}
|
||||
try:
|
||||
response = requests.get(url, headers=headers)
|
||||
response = requests.get(url, headers=headers, timeout=10)
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
return data.get("properties", {})
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ class NotionListPages(LCToolComponent):
|
|||
return f"Invalid JSON format for query: {e}"
|
||||
|
||||
try:
|
||||
response = requests.post(url, headers=headers, json=query_payload)
|
||||
response = requests.post(url, headers=headers, json=query_payload, timeout=10)
|
||||
response.raise_for_status()
|
||||
results = response.json()
|
||||
return results["results"]
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ class NotionUserList(LCToolComponent):
|
|||
"Notion-Version": "2022-06-28",
|
||||
}
|
||||
|
||||
response = requests.get(url, headers=headers)
|
||||
response = requests.get(url, headers=headers, timeout=10)
|
||||
response.raise_for_status()
|
||||
|
||||
data = response.json()
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ class NotionPageContent(LCToolComponent):
|
|||
"Notion-Version": "2022-06-28",
|
||||
}
|
||||
try:
|
||||
blocks_response = requests.get(blocks_url, headers=headers)
|
||||
blocks_response = requests.get(blocks_url, headers=headers, timeout=10)
|
||||
blocks_response.raise_for_status()
|
||||
blocks_data = blocks_response.json()
|
||||
return self.parse_blocks(blocks_data.get("results", []))
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ class NotionSearch(LCToolComponent):
|
|||
"sort": {"direction": sort_direction, "timestamp": "last_edited_time"},
|
||||
}
|
||||
|
||||
response = requests.post(url, headers=headers, json=data)
|
||||
response = requests.post(url, headers=headers, json=data, timeout=10)
|
||||
response.raise_for_status()
|
||||
|
||||
results = response.json()
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ class NotionPageUpdate(LCToolComponent):
|
|||
|
||||
try:
|
||||
logger.info(f"Sending request to Notion API: URL: {url}, Data: {json.dumps(data)}")
|
||||
response = requests.patch(url, headers=headers, json=data)
|
||||
response = requests.patch(url, headers=headers, json=data, timeout=10)
|
||||
response.raise_for_status()
|
||||
updated_page = response.json()
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ class JsonAgentComponent(LCAgentComponent):
|
|||
path = Path(self.path)
|
||||
if path.suffix in ("yaml", "yml"):
|
||||
with path.open(encoding="utf-8") as file:
|
||||
yaml_dict = yaml.load(file, Loader=yaml.FullLoader)
|
||||
yaml_dict = yaml.safe_load(file)
|
||||
spec = JsonSpec(dict_=yaml_dict)
|
||||
else:
|
||||
spec = JsonSpec.from_file(path)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class OpenAPIAgentComponent(LCAgentComponent):
|
|||
path = Path(self.path)
|
||||
if path.suffix in ("yaml", "yml"):
|
||||
with path.open(encoding="utf-8") as file:
|
||||
yaml_dict = yaml.load(file, Loader=yaml.FullLoader)
|
||||
yaml_dict = yaml.safe_load(file)
|
||||
spec = JsonSpec(dict_=yaml_dict)
|
||||
else:
|
||||
spec = JsonSpec.from_file(path)
|
||||
|
|
|
|||
|
|
@ -81,7 +81,9 @@ class GoogleDriveComponent(Component):
|
|||
msg = f"Error loading documents: {e}"
|
||||
raise ValueError(msg) from e
|
||||
|
||||
assert len(docs) == 1, "Expected a single document to be loaded."
|
||||
if len(docs) != 1:
|
||||
msg = "Expected a single document to be loaded."
|
||||
raise ValueError(msg)
|
||||
|
||||
data = docs_to_data(docs)
|
||||
# Return the loaded documents
|
||||
|
|
|
|||
|
|
@ -34,7 +34,9 @@ class EmbeddingSimilarityComponent(Component):
|
|||
embedding_vectors: list[Data] = self.embedding_vectors
|
||||
|
||||
# Assert that the list contains exactly two Data objects
|
||||
assert len(embedding_vectors) == 2, "Exactly two embedding vectors are required." # noqa: PLR2004
|
||||
if len(embedding_vectors) != 2: # noqa: PLR2004
|
||||
msg = "Exactly two embedding vectors are required."
|
||||
raise ValueError(msg)
|
||||
|
||||
embedding_1 = np.array(embedding_vectors[0].data["embeddings"])
|
||||
embedding_2 = np.array(embedding_vectors[1].data["embeddings"])
|
||||
|
|
|
|||
|
|
@ -29,7 +29,9 @@ class AIMLEmbeddingsImpl(BaseModel, Embeddings):
|
|||
for index, future in futures:
|
||||
try:
|
||||
result_data = future.result()
|
||||
assert len(result_data["data"]) == 1, "Expected one embedding"
|
||||
if len(result_data["data"]) != 1:
|
||||
msg = "Expected one embedding"
|
||||
raise ValueError(msg)
|
||||
embeddings[index] = result_data["data"][0]["embedding"]
|
||||
except (
|
||||
httpx.HTTPStatusError,
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class GroqModel(LCModelComponent):
|
|||
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
|
||||
|
||||
try:
|
||||
response = requests.get(url, headers=headers)
|
||||
response = requests.get(url, headers=headers, timeout=10)
|
||||
response.raise_for_status()
|
||||
model_list = response.json()
|
||||
return [model["id"] for model in model_list.get("data", [])]
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ class AstraDBCQLToolComponent(LCToolComponent):
|
|||
if self.projection_fields != "*":
|
||||
url += f'&fields={urllib.parse.quote(self.projection_fields.replace(" ", ""))}'
|
||||
|
||||
res = requests.request("GET", url=url, headers=headers)
|
||||
res = requests.request("GET", url=url, headers=headers, timeout=10)
|
||||
|
||||
if int(res.status_code) >= HTTPStatus.BAD_REQUEST:
|
||||
return res.text
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ class SearXNGToolComponent(LCToolComponent):
|
|||
try:
|
||||
url = f"{field_value}/config"
|
||||
|
||||
response = requests.get(url=url, headers=self.search_headers.copy())
|
||||
response = requests.get(url=url, headers=self.search_headers.copy(), timeout=10)
|
||||
data = None
|
||||
if response.headers.get("Content-Encoding") == "zstd":
|
||||
data = json.loads(response.content)
|
||||
|
|
@ -105,6 +105,7 @@ class SearXNGToolComponent(LCToolComponent):
|
|||
"language": SearxSearch._language,
|
||||
"format": "json",
|
||||
},
|
||||
timeout=10,
|
||||
).json()
|
||||
|
||||
num_results = min(SearxSearch._max_results, len(response["results"]))
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ class CodeParser:
|
|||
|
||||
# Handle cases where the type is not found in the constructed environment
|
||||
with contextlib.suppress(NameError):
|
||||
return_type = eval(return_type_str, eval_env)
|
||||
return_type = eval(return_type_str, eval_env) # noqa: S307
|
||||
|
||||
func = CallableCodeDetails(
|
||||
name=node.name,
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ from grandalf.graphs import Vertex as GrandalfVertex
|
|||
from grandalf.layouts import SugiyamaLayout
|
||||
from grandalf.routing import EdgeViewer, route_with_lines
|
||||
|
||||
MINIMUM_EDGE_VIEW_POINTS = 2
|
||||
|
||||
|
||||
class VertexViewer:
|
||||
"""Class to define vertex box boundaries that will be accounted for during graph building by grandalf."""
|
||||
|
|
@ -41,8 +43,12 @@ class AsciiCanvas:
|
|||
"""Class for drawing in ASCII."""
|
||||
|
||||
def __init__(self, cols, lines) -> None:
|
||||
assert cols > 1
|
||||
assert lines > 1
|
||||
if cols <= 1:
|
||||
msg = "cols must be greater than 1"
|
||||
raise ValueError(msg)
|
||||
if lines <= 1:
|
||||
msg = "lines must be greater than 1"
|
||||
raise ValueError(msg)
|
||||
self.cols = cols
|
||||
self.lines = lines
|
||||
self.canvas = [[" "] * cols for _ in range(lines)]
|
||||
|
|
@ -60,9 +66,15 @@ class AsciiCanvas:
|
|||
|
||||
def point(self, x, y, char) -> None:
|
||||
"""Create a point on ASCII canvas."""
|
||||
assert len(char) == 1
|
||||
assert 0 <= x < self.cols
|
||||
assert 0 <= y < self.lines
|
||||
if len(char) != 1:
|
||||
msg = "char must be a single character"
|
||||
raise ValueError(msg)
|
||||
if x < 0 or x >= self.cols:
|
||||
msg = "x is out of bounds"
|
||||
raise ValueError(msg)
|
||||
if y < 0 or y >= self.lines:
|
||||
msg = "y is out of bounds"
|
||||
raise ValueError(msg)
|
||||
self.canvas[y][x] = char
|
||||
|
||||
def line(self, x0, y0, x1, y1, char) -> None:
|
||||
|
|
@ -92,8 +104,12 @@ class AsciiCanvas:
|
|||
|
||||
def box(self, x0, y0, width, height) -> None:
|
||||
"""Create a box on ASCII canvas."""
|
||||
assert width > 1
|
||||
assert height > 1
|
||||
if width <= 1:
|
||||
msg = "width must be greater than 1"
|
||||
raise ValueError(msg)
|
||||
if height <= 1:
|
||||
msg = "height must be greater than 1"
|
||||
raise ValueError(msg)
|
||||
width -= 1
|
||||
height -= 1
|
||||
|
||||
|
|
@ -161,7 +177,9 @@ def draw_graph(vertexes, edges, *, return_ascii=True):
|
|||
canvas = AsciiCanvas(canvas_cols, canvas_lines)
|
||||
|
||||
for edge in sug.g.sE:
|
||||
assert len(edge.view._pts) > 1
|
||||
if len(edge.view._pts) < MINIMUM_EDGE_VIEW_POINTS:
|
||||
msg = "edge.view._pts must have at least 2 points"
|
||||
raise ValueError(msg)
|
||||
for index in range(1, len(edge.view._pts)):
|
||||
start = edge.view._pts[index - 1]
|
||||
end = edge.view._pts[index]
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ async def flow_function({func_args}):
|
|||
|
||||
compiled_func = compile(func_body, "<string>", "exec")
|
||||
local_scope: dict = {}
|
||||
exec(compiled_func, globals(), local_scope)
|
||||
exec(compiled_func, globals(), local_scope) # noqa: S102
|
||||
return local_scope["flow_function"]
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ from langflow.schema.table import Column, TableSchema
|
|||
class FieldTypes(str, Enum):
|
||||
TEXT = "str"
|
||||
INTEGER = "int"
|
||||
PASSWORD = "str" # noqa: PIE796
|
||||
PASSWORD = "str" # noqa: PIE796, S105
|
||||
FLOAT = "float"
|
||||
BOOLEAN = "bool"
|
||||
DICT = "dict"
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ def create_input_schema(inputs: list["InputTypes"]) -> type[BaseModel]:
|
|||
literal_string = f"Literal{input_model.options}"
|
||||
# validate that the literal_string is a valid literal
|
||||
|
||||
field_type = eval(literal_string, {"Literal": Literal})
|
||||
field_type = eval(literal_string, {"Literal": Literal}) # noqa: S307
|
||||
if hasattr(input_model, "is_list") and input_model.is_list:
|
||||
field_type = list[field_type] # type: ignore[valid-type]
|
||||
if input_model.name:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
DEFAULT_SUPERUSER = "langflow"
|
||||
DEFAULT_SUPERUSER_PASSWORD = "langflow"
|
||||
DEFAULT_SUPERUSER_PASSWORD = "langflow" # noqa: S105
|
||||
VARIABLES_TO_GET_FROM_ENVIRONMENT = [
|
||||
"OPENAI_API_KEY",
|
||||
"ANTHROPIC_API_KEY",
|
||||
|
|
|
|||
|
|
@ -22,7 +22,12 @@ class KubernetesSecretManager:
|
|||
# initialize the Kubernetes API client
|
||||
self.core_api = client.CoreV1Api()
|
||||
|
||||
def create_secret(self, name: str, data: dict, secret_type: str = "Opaque"):
|
||||
def create_secret(
|
||||
self,
|
||||
name: str,
|
||||
data: dict,
|
||||
secret_type: str = "Opaque", # noqa: S107
|
||||
):
|
||||
"""Create a new secret in the specified namespace.
|
||||
|
||||
Args:
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ ignore = [
|
|||
# Rules that are TODOs
|
||||
"ANN", # Missing type annotations
|
||||
"D1", # Missing docstrings
|
||||
"S",
|
||||
"SLF",
|
||||
]
|
||||
|
||||
|
|
@ -67,6 +66,12 @@ ignore = [
|
|||
"langflow/api/v1/*" = [
|
||||
"TCH", # FastAPI needs to evaluate types at runtime
|
||||
]
|
||||
"langflow/{components/tools/python_code_structured_tool.py,custom/code_parser/code_parser.py,utils/validate.py}" = [
|
||||
"S102", # Use of exec
|
||||
]
|
||||
"langflow/services/cache/*" = [
|
||||
"S301", # Use of pickle
|
||||
]
|
||||
|
||||
[tool.uv]
|
||||
dev-dependencies = [
|
||||
|
|
@ -154,6 +159,7 @@ dependencies = [
|
|||
"clickhouse-connect==0.7.19",
|
||||
"assemblyai>=0.33.0",
|
||||
"fastapi-pagination>=0.12.29",
|
||||
"defusedxml>=0.7.1",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue