From 33c9bf1adc8f20a4edddbd3012c405af8350e372 Mon Sep 17 00:00:00 2001 From: Mason Daugherty Date: Mon, 30 Jun 2025 14:01:32 -0400 Subject: [PATCH] langchain-openai[patch]: Add ruff bandit rules to linter (#31788) --- .../chat_models/_client_utils.py | 4 ++-- .../openai/langchain_openai/llms/base.py | 6 ++++-- libs/partners/openai/pyproject.toml | 8 +++++++- .../openai/tests/unit_tests/test_secrets.py | 18 ++++++++++-------- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/libs/partners/openai/langchain_openai/chat_models/_client_utils.py b/libs/partners/openai/langchain_openai/chat_models/_client_utils.py index d10b815a9ea..c41f500a454 100644 --- a/libs/partners/openai/langchain_openai/chat_models/_client_utils.py +++ b/libs/partners/openai/langchain_openai/chat_models/_client_utils.py @@ -23,7 +23,7 @@ class _SyncHttpxClientWrapper(openai.DefaultHttpxClient): try: self.close() - except Exception: + except Exception: # noqa: S110 pass @@ -37,7 +37,7 @@ class _AsyncHttpxClientWrapper(openai.DefaultAsyncHttpxClient): try: # TODO(someday): support non asyncio runtimes here asyncio.get_running_loop().create_task(self.aclose()) - except Exception: + except Exception: # noqa: S110 pass diff --git a/libs/partners/openai/langchain_openai/llms/base.py b/libs/partners/openai/langchain_openai/llms/base.py index 1bdd4283b3f..e22b7b01712 100644 --- a/libs/partners/openai/langchain_openai/llms/base.py +++ b/libs/partners/openai/langchain_openai/llms/base.py @@ -310,7 +310,8 @@ class BaseOpenAI(BaseLLM): generation = chunk else: generation += chunk - assert generation is not None + if generation is None: + raise ValueError("Generation is empty after streaming.") choices.append( { "text": generation.text, @@ -378,7 +379,8 @@ class BaseOpenAI(BaseLLM): generation = chunk else: generation += chunk - assert generation is not None + if generation is None: + raise ValueError("Generation is empty after streaming.") choices.append( { "text": generation.text, diff --git a/libs/partners/openai/pyproject.toml b/libs/partners/openai/pyproject.toml index b930fa93821..f088188daf4 100644 --- a/libs/partners/openai/pyproject.toml +++ b/libs/partners/openai/pyproject.toml @@ -64,7 +64,7 @@ ignore_missing_imports = true target-version = "py39" [tool.ruff.lint] -select = ["E", "F", "I", "T201", "UP"] +select = ["E", "F", "I", "T201", "UP", "S"] ignore = [ "UP007", ] [tool.ruff.format] @@ -85,3 +85,9 @@ asyncio_mode = "auto" filterwarnings = [ "ignore::langchain_core._api.beta_decorator.LangChainBetaWarning", ] + +[tool.ruff.lint.extend-per-file-ignores] +"tests/**/*.py" = [ + "S101", # Tests need assertions + "S311", # Standard pseudo-random generators are not suitable for cryptographic purposes +] \ No newline at end of file diff --git a/libs/partners/openai/tests/unit_tests/test_secrets.py b/libs/partners/openai/tests/unit_tests/test_secrets.py index f0540997fd8..aa1484058e0 100644 --- a/libs/partners/openai/tests/unit_tests/test_secrets.py +++ b/libs/partners/openai/tests/unit_tests/test_secrets.py @@ -14,6 +14,8 @@ from langchain_openai import ( OpenAIEmbeddings, ) +AZURE_AD_TOKEN = "secret-api-key" # noqa: S105 + def test_chat_openai_secrets() -> None: o = ChatOpenAI(openai_api_key="foo") # type: ignore[call-arg] @@ -37,7 +39,7 @@ def test_azure_chat_openai_secrets() -> None: o = AzureChatOpenAI( # type: ignore[call-arg] openai_api_key="foo1", azure_endpoint="endpoint", - azure_ad_token="foo2", # type: ignore[arg-type] + azure_ad_token=AZURE_AD_TOKEN, # type: ignore[arg-type] api_version="version", ) s = str(o) @@ -49,7 +51,7 @@ def test_azure_openai_secrets() -> None: o = AzureOpenAI( # type: ignore[call-arg] openai_api_key="foo1", azure_endpoint="endpoint", - azure_ad_token="foo2", # type: ignore[arg-type] + azure_ad_token=AZURE_AD_TOKEN, # type: ignore[arg-type] api_version="version", ) s = str(o) @@ -61,7 +63,7 @@ def test_azure_openai_embeddings_secrets() -> None: o = AzureOpenAIEmbeddings( # type: ignore[call-arg] openai_api_key="foo1", azure_endpoint="endpoint", - azure_ad_token="foo2", # type: ignore[arg-type] + azure_ad_token=AZURE_AD_TOKEN, # type: ignore[arg-type] api_version="version", ) s = str(o) @@ -77,7 +79,7 @@ def test_azure_openai_api_key_is_secret_string(model_class: type) -> None: model = model_class( openai_api_key="secret-api-key", azure_endpoint="endpoint", - azure_ad_token="secret-ad-token", + azure_ad_token=AZURE_AD_TOKEN, api_version="version", ) assert isinstance(model.openai_api_key, SecretStr) @@ -115,7 +117,7 @@ def test_azure_openai_api_key_masked_when_passed_via_constructor( model = model_class( openai_api_key="secret-api-key", azure_endpoint="endpoint", - azure_ad_token="secret-ad-token", + azure_ad_token=AZURE_AD_TOKEN, api_version="version", ) print(model.openai_api_key, end="") # noqa: T201 @@ -139,11 +141,11 @@ def test_azure_openai_uses_actual_secret_value_from_secretstr( model = model_class( openai_api_key="secret-api-key", azure_endpoint="endpoint", - azure_ad_token="secret-ad-token", + azure_ad_token=AZURE_AD_TOKEN, api_version="version", ) assert cast(SecretStr, model.openai_api_key).get_secret_value() == "secret-api-key" - assert cast(SecretStr, model.azure_ad_token).get_secret_value() == "secret-ad-token" + assert cast(SecretStr, model.azure_ad_token).get_secret_value() == AZURE_AD_TOKEN @pytest.mark.parametrize("model_class", [ChatOpenAI, OpenAI, OpenAIEmbeddings]) @@ -195,7 +197,7 @@ def test_azure_serialized_secrets(model_class: type) -> None: assert serialized["kwargs"]["openai_api_key"]["id"] == ["AZURE_OPENAI_API_KEY"] model = model_class( - azure_ad_token="secret-token", api_version="foo", azure_endpoint="foo" + azure_ad_token=AZURE_AD_TOKEN, api_version="foo", azure_endpoint="foo" ) serialized = dumpd(model) assert serialized["kwargs"]["azure_ad_token"]["id"] == ["AZURE_OPENAI_AD_TOKEN"]