From 1ee8aceaeeef1bc98e409f1c157fb1d0bf9a50c9 Mon Sep 17 00:00:00 2001 From: Manthan Surkar <42006277+thesmallstar@users.noreply.github.com> Date: Wed, 5 Mar 2025 21:19:25 +0530 Subject: [PATCH] community: fix Jira API wrapper failing initialization with cloud param (#30117) ### **Description** Converts the boolean `jira_cloud` parameter in the Jira API Wrapper to a string before initializing the Jira Client. Also adds tests for the same. ### **Issue** [Jira API Wrapper Bug](https://github.com/thesmallstar/langchain/blob/8abb65e138a1fa21a3bf3e26078a0c4a2f316b09/libs/community/langchain_community/utilities/jira.py#L47) ```python jira_cloud_str = get_from_dict_or_env(values, "jira_cloud", "JIRA_CLOUD") jira_cloud = jira_cloud_str.lower() == "true" ``` The above code has a bug where the value of `"jira_cloud"` is a boolean. If it is passed, calling `.lower()` on a boolean raises an error. Additionally, `False` cannot be passed explicitly since `get_from_dict_or_env` falls back to environment variables. Relevant code in `langchain_core`: [Source](https://github.com/thesmallstar/langchain/blob/master/.venv/lib/python3.13/site-packages/langchain_core/utils/env.py#L46) ```python if isinstance(key, str) and key in data and data[key]: # Here, data[key] is False ``` This PR fixes both issues. ### **Twitter Handle** [Manthan Surkar](https://x.com/manthan_surkar) --- .../langchain_community/utilities/jira.py | 3 + .../unit_tests/jira/test_jira_api_wrapper.py | 62 +++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 libs/community/tests/unit_tests/jira/test_jira_api_wrapper.py diff --git a/libs/community/langchain_community/utilities/jira.py b/libs/community/langchain_community/utilities/jira.py index 1d9adb1d073..ad8258e363d 100644 --- a/libs/community/langchain_community/utilities/jira.py +++ b/libs/community/langchain_community/utilities/jira.py @@ -40,6 +40,9 @@ class JiraAPIWrapper(BaseModel): ) values["jira_instance_url"] = jira_instance_url + if "jira_cloud" in values and values["jira_cloud"] is not None: + values["jira_cloud"] = str(values["jira_cloud"]) + jira_cloud_str = get_from_dict_or_env(values, "jira_cloud", "JIRA_CLOUD") jira_cloud = jira_cloud_str.lower() == "true" values["jira_cloud"] = jira_cloud diff --git a/libs/community/tests/unit_tests/jira/test_jira_api_wrapper.py b/libs/community/tests/unit_tests/jira/test_jira_api_wrapper.py new file mode 100644 index 00000000000..ac73f3f5f51 --- /dev/null +++ b/libs/community/tests/unit_tests/jira/test_jira_api_wrapper.py @@ -0,0 +1,62 @@ +from unittest.mock import MagicMock, patch + +import pytest + +from langchain_community.utilities.jira import JiraAPIWrapper + + +@pytest.fixture +def mock_jira(): # type: ignore + with patch("atlassian.Jira") as mock_jira: + yield mock_jira + + +@pytest.mark.requires("atlassian") +class TestJiraAPIWrapper: + def test_jira_api_wrapper(self, mock_jira: MagicMock) -> None: + """Test for Jira API Wrapper using mocks""" + # Configure the mock instance + mock_jira_instance = mock_jira.return_value + + # Mock projects method to return mock projects + mock_project1 = MagicMock(key="PROJ1") + mock_project2 = MagicMock(key="PROJ2") + + # Set up the mock to return our mock projects + mock_jira_instance.projects.return_value = [mock_project1, mock_project2] + + # Initialize wrapper with mocks in place + jira_wrapper = JiraAPIWrapper( + jira_username="test_user", + jira_api_token="test_token", + jira_instance_url="https://test.atlassian.net", + jira_cloud=True, + ) + + mock_jira.assert_called_once_with( + url="https://test.atlassian.net", + username="test_user", + password="test_token", + cloud=True, + ) + + # Test get_projects function + result = jira_wrapper.run("get_projects", "") + + # Verify the mock was called and the result contains expected info + mock_jira_instance.projects.assert_called_once() + assert result.startswith("Found 2 projects") + + def test_jira_api_wrapper_with_cloud_false(self, mock_jira: MagicMock) -> None: + JiraAPIWrapper( + jira_username="test_user", + jira_api_token="test_token", + jira_instance_url="https://test.atlassian.net", + jira_cloud=False, + ) + mock_jira.assert_called_once_with( + url="https://test.atlassian.net", + username="test_user", + password="test_token", + cloud=False, + )