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](8abb65e138/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)
This commit is contained in:
Manthan Surkar 2025-03-05 21:19:25 +05:30 committed by GitHub
parent c599ba47d5
commit 1ee8aceaee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 65 additions and 0 deletions

View File

@ -40,6 +40,9 @@ class JiraAPIWrapper(BaseModel):
) )
values["jira_instance_url"] = jira_instance_url 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_str = get_from_dict_or_env(values, "jira_cloud", "JIRA_CLOUD")
jira_cloud = jira_cloud_str.lower() == "true" jira_cloud = jira_cloud_str.lower() == "true"
values["jira_cloud"] = jira_cloud values["jira_cloud"] = jira_cloud

View File

@ -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,
)