fix: update tests for module rename from mcp_cordra to cordra_mcp

- Updated all import statements in test files
- Added types-requests dependency for mypy type checking
- Fixed code formatting with ruff
This commit is contained in:
Daniel Bauer
2025-06-30 12:01:53 +02:00
parent 4102860d98
commit 96df10adb0
5 changed files with 148 additions and 111 deletions

View File

@@ -60,4 +60,5 @@ dev = [
"mypy>=1.16.1", "mypy>=1.16.1",
"pytest-asyncio>=1.0.0", "pytest-asyncio>=1.0.0",
"ruff>=0.12.1", "ruff>=0.12.1",
"types-requests>=2.32.4.20250611",
] ]

View File

@@ -1,7 +1,7 @@
"""Cordra client wrapper using HTTP requests.""" """Cordra client wrapper using HTTP requests."""
import logging import logging
from typing import Any from typing import Any, cast
import requests import requests
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
@@ -19,21 +19,26 @@ class DigitalObject(BaseModel):
content: dict[str, Any] = Field(description="Object content as JSON") content: dict[str, Any] = Field(description="Object content as JSON")
metadata: dict[str, Any] | None = Field(default=None, description="Object metadata") metadata: dict[str, Any] | None = Field(default=None, description="Object metadata")
acl: dict[str, Any] | None = Field(default=None, description="Access control list") acl: dict[str, Any] | None = Field(default=None, description="Access control list")
payloads: list[dict[str, Any]] | None = Field(default=None, description="List of payloads") payloads: list[dict[str, Any]] | None = Field(
default=None, description="List of payloads"
)
class CordraClientError(Exception): class CordraClientError(Exception):
"""Base exception for Cordra client errors.""" """Base exception for Cordra client errors."""
pass pass
class CordraNotFoundError(CordraClientError): class CordraNotFoundError(CordraClientError):
"""Exception raised when an object is not found.""" """Exception raised when an object is not found."""
pass pass
class CordraAuthenticationError(CordraClientError): class CordraAuthenticationError(CordraClientError):
"""Exception raised for authentication/authorization failures.""" """Exception raised for authentication/authorization failures."""
pass pass
@@ -54,7 +59,9 @@ class CordraClient:
if config.username and config.password: if config.username and config.password:
self.session.auth = (config.username, config.password) self.session.auth = (config.username, config.password)
elif config.username or config.password: elif config.username or config.password:
logger.warning("Only username or password provided, not both. Authentication may fail.") logger.warning(
"Only username or password provided, not both. Authentication may fail."
)
def _handle_http_error(self, response: requests.Response, context: str) -> None: def _handle_http_error(self, response: requests.Response, context: str) -> None:
"""Handle HTTP errors and raise appropriate exceptions. """Handle HTTP errors and raise appropriate exceptions.
@@ -72,7 +79,9 @@ class CordraClient:
if status_code == 404: if status_code == 404:
raise CordraNotFoundError(f"{context}: Resource not found") raise CordraNotFoundError(f"{context}: Resource not found")
elif status_code in (401, 403): elif status_code in (401, 403):
raise CordraAuthenticationError(f"{context}: Authentication failed (HTTP {status_code})") raise CordraAuthenticationError(
f"{context}: Authentication failed (HTTP {status_code})"
)
elif status_code >= 500: elif status_code >= 500:
raise CordraClientError(f"{context}: Server error (HTTP {status_code})") raise CordraClientError(f"{context}: Server error (HTTP {status_code})")
else: else:
@@ -100,21 +109,25 @@ class CordraClient:
response = self.session.get(url, params=params, timeout=self.config.timeout) response = self.session.get(url, params=params, timeout=self.config.timeout)
if not response.ok: if not response.ok:
self._handle_http_error(response, f"Failed to retrieve object {object_id}") self._handle_http_error(
response, f"Failed to retrieve object {object_id}"
)
cordra_obj = response.json() cordra_obj = response.json()
return DigitalObject( return DigitalObject(
id=object_id, id=object_id,
type=cordra_obj.get('type', ''), type=cordra_obj.get("type", ""),
content=cordra_obj.get('content', cordra_obj), content=cordra_obj.get("content", cordra_obj),
metadata=cordra_obj.get('metadata'), metadata=cordra_obj.get("metadata"),
acl=cordra_obj.get('acl'), acl=cordra_obj.get("acl"),
payloads=cordra_obj.get('payloads'), payloads=cordra_obj.get("payloads"),
) )
except requests.RequestException as e: except requests.RequestException as e:
raise CordraClientError(f"Failed to retrieve object {object_id}: {e}") from e raise CordraClientError(
f"Failed to retrieve object {object_id}: {e}"
) from e
async def find(self, query: str) -> list[dict[str, Any]]: async def find(self, query: str) -> list[dict[str, Any]]:
"""Find objects using a Cordra query. """Find objects using a Cordra query.
@@ -137,18 +150,22 @@ class CordraClient:
response = self.session.get(url, params=params, timeout=self.config.timeout) response = self.session.get(url, params=params, timeout=self.config.timeout)
if not response.ok: if not response.ok:
self._handle_http_error(response, f"Failed to search with query '{query}'") self._handle_http_error(
response, f"Failed to search with query '{query}'"
)
search_result = response.json() search_result = response.json()
# Extract the results array from the response # Extract the results array from the response
if isinstance(search_result, dict) and 'results' in search_result: if isinstance(search_result, dict) and "results" in search_result:
return search_result['results'] return search_result["results"] # type: ignore
else: else:
return [] return []
except requests.RequestException as e: except requests.RequestException as e:
raise CordraClientError(f"Failed to search with query '{query}': {e}") from e raise CordraClientError(
f"Failed to search with query '{query}': {e}"
) from e
async def get_schema(self, schema_name: str) -> DigitalObject: async def get_schema(self, schema_name: str) -> DigitalObject:
"""Retrieve a schema definition by its name. """Retrieve a schema definition by its name.
@@ -177,9 +194,11 @@ class CordraClient:
schema_data = schemas[0] schema_data = schemas[0]
# Get the full schema object using its ID # Get the full schema object using its ID
return await self.get_object(schema_data['id']) return await self.get_object(schema_data["id"])
except (CordraNotFoundError, CordraAuthenticationError): except (CordraNotFoundError, CordraAuthenticationError):
raise raise
except Exception as e: except Exception as e:
raise CordraClientError(f"Failed to retrieve schema '{schema_name}': {e}") from e raise CordraClientError(
f"Failed to retrieve schema '{schema_name}': {e}"
) from e

View File

@@ -3,13 +3,14 @@
from unittest.mock import patch from unittest.mock import patch
import pytest import pytest
from mcp_cordra.client import (
from cordra_mcp.client import (
CordraClient, CordraClient,
CordraClientError, CordraClientError,
CordraNotFoundError, CordraNotFoundError,
DigitalObject, DigitalObject,
) )
from mcp_cordra.config import CordraConfig from cordra_mcp.config import CordraConfig
@pytest.fixture @pytest.fixture
@@ -42,15 +43,15 @@ def mock_cordra_object():
"name": "file1.txt", "name": "file1.txt",
"filename": "file1.txt", "filename": "file1.txt",
"size": 1024, "size": 1024,
"mediaType": "text/plain" "mediaType": "text/plain",
}, },
{ {
"name": "file2.pdf", "name": "file2.pdf",
"filename": "file2.pdf", "filename": "file2.pdf",
"size": 2048, "size": 2048,
"mediaType": "application/pdf" "mediaType": "application/pdf",
} },
] ],
} }
@@ -70,7 +71,7 @@ class TestDigitalObject:
"name": "file1.txt", "name": "file1.txt",
"mediaType": "text/plain", "mediaType": "text/plain",
"size": 1024, "size": 1024,
"filename": "file1.txt" "filename": "file1.txt",
} }
], ],
) )
@@ -89,11 +90,7 @@ class TestDigitalObject:
def test_digital_object_optional_fields(self): def test_digital_object_optional_fields(self):
"""Test DigitalObject with only required fields.""" """Test DigitalObject with only required fields."""
obj = DigitalObject( obj = DigitalObject(id="test/123", type="TestType", content={"title": "Test"})
id="test/123",
type="TestType",
content={"title": "Test"}
)
assert obj.id == "test/123" assert obj.id == "test/123"
assert obj.type == "TestType" assert obj.type == "TestType"
@@ -111,7 +108,7 @@ class TestCordraClient:
client = CordraClient(config) client = CordraClient(config)
assert client.config == config assert client.config == config
@patch('mcp_cordra.client.requests.Session.get') @patch("cordra_mcp.client.requests.Session.get")
async def test_get_object_success(self, mock_get, client, mock_cordra_object): async def test_get_object_success(self, mock_get, client, mock_cordra_object):
"""Test successful object retrieval.""" """Test successful object retrieval."""
mock_response = mock_get.return_value mock_response = mock_get.return_value
@@ -124,7 +121,10 @@ class TestCordraClient:
assert isinstance(result, DigitalObject) assert isinstance(result, DigitalObject)
assert result.id == "test/123" assert result.id == "test/123"
assert result.type == "TestType" assert result.type == "TestType"
assert result.content == {"title": "Test Object", "description": "A test object"} assert result.content == {
"title": "Test Object",
"description": "A test object",
}
assert result.metadata == {"created": "2023-01-01", "modified": "2023-01-02"} assert result.metadata == {"created": "2023-01-01", "modified": "2023-01-02"}
assert result.acl == {"read": ["public"], "write": ["admin"]} assert result.acl == {"read": ["public"], "write": ["admin"]}
assert result.payloads and len(result.payloads) == 2 assert result.payloads and len(result.payloads) == 2
@@ -132,10 +132,10 @@ class TestCordraClient:
mock_get.assert_called_once_with( mock_get.assert_called_once_with(
"https://test.example.com/objects/test/123", "https://test.example.com/objects/test/123",
params={"full": "true"}, params={"full": "true"},
timeout=30 timeout=30,
) )
@patch('mcp_cordra.client.requests.Session.get') @patch("cordra_mcp.client.requests.Session.get")
async def test_get_object_not_found(self, mock_get, client): async def test_get_object_not_found(self, mock_get, client):
"""Test object not found exception.""" """Test object not found exception."""
mock_response = mock_get.return_value mock_response = mock_get.return_value
@@ -147,10 +147,11 @@ class TestCordraClient:
assert "Resource not found" in str(exc_info.value) assert "Resource not found" in str(exc_info.value)
@patch('mcp_cordra.client.requests.Session.get') @patch("cordra_mcp.client.requests.Session.get")
async def test_get_object_general_error(self, mock_get, client): async def test_get_object_general_error(self, mock_get, client):
"""Test general error handling.""" """Test general error handling."""
from requests import RequestException from requests import RequestException
mock_get.side_effect = RequestException("Connection failed") mock_get.side_effect = RequestException("Connection failed")
with pytest.raises(CordraClientError) as exc_info: with pytest.raises(CordraClientError) as exc_info:
@@ -158,16 +159,16 @@ class TestCordraClient:
assert "Failed to retrieve object test/123" in str(exc_info.value) assert "Failed to retrieve object test/123" in str(exc_info.value)
@patch('mcp_cordra.client.requests.Session.get') @patch("cordra_mcp.client.requests.Session.get")
async def test_find_success(self, mock_get, client): async def test_find_success(self, mock_get, client):
"""Test successful find operation.""" """Test successful find operation."""
mock_response_data = { mock_response_data = {
"results": [ "results": [
{"name": "User", "identifier": "test/user-schema"}, {"name": "User", "identifier": "test/user-schema"},
{"name": "Project", "identifier": "test/project-schema"}, {"name": "Project", "identifier": "test/project-schema"},
{"name": "Document", "identifier": "test/doc-schema"} {"name": "Document", "identifier": "test/doc-schema"},
], ],
"size": 3 "size": 3,
} }
mock_response = mock_get.return_value mock_response = mock_get.return_value
mock_response.status_code = 200 mock_response.status_code = 200
@@ -184,10 +185,10 @@ class TestCordraClient:
mock_get.assert_called_once_with( mock_get.assert_called_once_with(
"https://test.example.com/search", "https://test.example.com/search",
params={"query": "type:Schema"}, params={"query": "type:Schema"},
timeout=30 timeout=30,
) )
@patch('mcp_cordra.client.requests.Session.get') @patch("cordra_mcp.client.requests.Session.get")
async def test_find_empty_results(self, mock_get, client): async def test_find_empty_results(self, mock_get, client):
"""Test find with empty results.""" """Test find with empty results."""
mock_response_data = {"results": [], "size": 0} mock_response_data = {"results": [], "size": 0}
@@ -202,10 +203,10 @@ class TestCordraClient:
mock_get.assert_called_once_with( mock_get.assert_called_once_with(
"https://test.example.com/search", "https://test.example.com/search",
params={"query": "type:NonExistent"}, params={"query": "type:NonExistent"},
timeout=30 timeout=30,
) )
@patch('mcp_cordra.client.requests.Session.get') @patch("cordra_mcp.client.requests.Session.get")
async def test_find_no_results_key(self, mock_get, client): async def test_find_no_results_key(self, mock_get, client):
"""Test find with response missing results key.""" """Test find with response missing results key."""
mock_response_data = {"size": 0} # No results key mock_response_data = {"size": 0} # No results key
@@ -218,10 +219,11 @@ class TestCordraClient:
assert result == [] assert result == []
@patch('mcp_cordra.client.requests.Session.get') @patch("cordra_mcp.client.requests.Session.get")
async def test_find_error(self, mock_get, client): async def test_find_error(self, mock_get, client):
"""Test find error handling.""" """Test find error handling."""
from requests import RequestException from requests import RequestException
mock_get.side_effect = RequestException("Search failed") mock_get.side_effect = RequestException("Search failed")
with pytest.raises(CordraClientError) as exc_info: with pytest.raises(CordraClientError) as exc_info:

View File

@@ -4,8 +4,9 @@ import json
from unittest.mock import AsyncMock, patch from unittest.mock import AsyncMock, patch
import pytest import pytest
from mcp_cordra.client import CordraClientError, CordraNotFoundError, DigitalObject
from mcp_cordra.server import get_cordra_object from cordra_mcp.client import CordraClientError, CordraNotFoundError, DigitalObject
from cordra_mcp.server import get_cordra_object
@pytest.fixture @pytest.fixture
@@ -35,7 +36,7 @@ def sample_digital_object():
class TestGetCordraObject: class TestGetCordraObject:
"""Test the get_cordra_object resource handler.""" """Test the get_cordra_object resource handler."""
@patch('mcp_cordra.server.cordra_client') @patch('cordra_mcp.server.cordra_client')
async def test_get_object_success(self, mock_client, sample_digital_object): async def test_get_object_success(self, mock_client, sample_digital_object):
"""Test successful object retrieval.""" """Test successful object retrieval."""
mock_client.get_object = AsyncMock(return_value=sample_digital_object) mock_client.get_object = AsyncMock(return_value=sample_digital_object)
@@ -55,7 +56,7 @@ class TestGetCordraObject:
# Verify the client was called with the correct object ID # Verify the client was called with the correct object ID
mock_client.get_object.assert_called_once_with("people/john-doe-123") mock_client.get_object.assert_called_once_with("people/john-doe-123")
@patch('mcp_cordra.server.cordra_client') @patch('cordra_mcp.server.cordra_client')
async def test_get_object_not_found(self, mock_client): async def test_get_object_not_found(self, mock_client):
"""Test object not found exception.""" """Test object not found exception."""
mock_client.get_object = AsyncMock( mock_client.get_object = AsyncMock(
@@ -68,7 +69,7 @@ class TestGetCordraObject:
assert "Object not found: people/nonexistent" in str(exc_info.value) assert "Object not found: people/nonexistent" in str(exc_info.value)
mock_client.get_object.assert_called_once_with("people/nonexistent") mock_client.get_object.assert_called_once_with("people/nonexistent")
@patch('mcp_cordra.server.cordra_client') @patch('cordra_mcp.server.cordra_client')
async def test_get_object_client_error(self, mock_client): async def test_get_object_client_error(self, mock_client):
"""Test general client error handling.""" """Test general client error handling."""
mock_client.get_object = AsyncMock( mock_client.get_object = AsyncMock(
@@ -82,7 +83,7 @@ class TestGetCordraObject:
assert "Connection failed" in str(exc_info.value) assert "Connection failed" in str(exc_info.value)
mock_client.get_object.assert_called_once_with("people/john-doe-123") mock_client.get_object.assert_called_once_with("people/john-doe-123")
@patch('mcp_cordra.server.cordra_client') @patch('cordra_mcp.server.cordra_client')
async def test_object_id_construction(self, mock_client, sample_digital_object): async def test_object_id_construction(self, mock_client, sample_digital_object):
"""Test that object ID is correctly constructed from prefix and suffix.""" """Test that object ID is correctly constructed from prefix and suffix."""
mock_client.get_object = AsyncMock(return_value=sample_digital_object) mock_client.get_object = AsyncMock(return_value=sample_digital_object)
@@ -98,7 +99,7 @@ class TestGetCordraObject:
await get_cordra_object(prefix, suffix) await get_cordra_object(prefix, suffix)
mock_client.get_object.assert_called_with(expected_id) mock_client.get_object.assert_called_with(expected_id)
@patch('mcp_cordra.server.cordra_client') @patch('cordra_mcp.server.cordra_client')
async def test_json_formatting(self, mock_client, sample_digital_object): async def test_json_formatting(self, mock_client, sample_digital_object):
"""Test that the returned JSON is properly formatted.""" """Test that the returned JSON is properly formatted."""
mock_client.get_object = AsyncMock(return_value=sample_digital_object) mock_client.get_object = AsyncMock(return_value=sample_digital_object)
@@ -120,7 +121,7 @@ class TestGetCordraObject:
assert "acl" in parsed_result assert "acl" in parsed_result
assert "payloads" in parsed_result assert "payloads" in parsed_result
@patch('mcp_cordra.server.cordra_client') @patch('cordra_mcp.server.cordra_client')
async def test_minimal_object(self, mock_client): async def test_minimal_object(self, mock_client):
"""Test handling of object with minimal data.""" """Test handling of object with minimal data."""
minimal_object = DigitalObject( minimal_object = DigitalObject(
@@ -147,7 +148,7 @@ class TestGetCordraObject:
class TestSchemaResourceFunctions: class TestSchemaResourceFunctions:
"""Test the schema resource functions.""" """Test the schema resource functions."""
@patch('mcp_cordra.server.cordra_client') @patch('cordra_mcp.server.cordra_client')
async def test_create_schema_resource_success(self, mock_client): async def test_create_schema_resource_success(self, mock_client):
"""Test successful schema resource creation.""" """Test successful schema resource creation."""
mock_schema = DigitalObject( mock_schema = DigitalObject(
@@ -157,7 +158,7 @@ class TestSchemaResourceFunctions:
) )
mock_client.get_schema = AsyncMock(return_value=mock_schema) mock_client.get_schema = AsyncMock(return_value=mock_schema)
from mcp_cordra.server import create_schema_resource from cordra_mcp.server import create_schema_resource
result = await create_schema_resource("User") result = await create_schema_resource("User")
# Verify the result is valid JSON # Verify the result is valid JSON
@@ -169,19 +170,19 @@ class TestSchemaResourceFunctions:
# Verify the client was called with correct schema name # Verify the client was called with correct schema name
mock_client.get_schema.assert_called_once_with("User") mock_client.get_schema.assert_called_once_with("User")
@patch('mcp_cordra.server.cordra_client') @patch('cordra_mcp.server.cordra_client')
async def test_create_schema_resource_not_found(self, mock_client): async def test_create_schema_resource_not_found(self, mock_client):
"""Test schema resource creation with schema not found.""" """Test schema resource creation with schema not found."""
mock_client.get_schema = AsyncMock(side_effect=CordraNotFoundError("Schema not found")) mock_client.get_schema = AsyncMock(side_effect=CordraNotFoundError("Schema not found"))
from mcp_cordra.server import create_schema_resource from cordra_mcp.server import create_schema_resource
with pytest.raises(RuntimeError) as exc_info: with pytest.raises(RuntimeError) as exc_info:
await create_schema_resource("NonExistent") await create_schema_resource("NonExistent")
assert "Schema not found: NonExistent" in str(exc_info.value) assert "Schema not found: NonExistent" in str(exc_info.value)
mock_client.get_schema.assert_called_once_with("NonExistent") mock_client.get_schema.assert_called_once_with("NonExistent")
@patch('mcp_cordra.server.cordra_client') @patch('cordra_mcp.server.cordra_client')
async def test_register_schema_resources_success(self, mock_client): async def test_register_schema_resources_success(self, mock_client):
"""Test successful schema resource registration.""" """Test successful schema resource registration."""
mock_schemas = [ mock_schemas = [
@@ -192,8 +193,8 @@ class TestSchemaResourceFunctions:
mock_client.find = AsyncMock(return_value=mock_schemas) mock_client.find = AsyncMock(return_value=mock_schemas)
# Mock the mcp.add_resource method # Mock the mcp.add_resource method
with patch('mcp_cordra.server.mcp') as mock_mcp: with patch('cordra_mcp.server.mcp') as mock_mcp:
from mcp_cordra.server import register_schema_resources from cordra_mcp.server import register_schema_resources
await register_schema_resources() await register_schema_resources()
# Verify the client was called with correct query # Verify the client was called with correct query
@@ -202,7 +203,7 @@ class TestSchemaResourceFunctions:
# Verify add_resource was called for each schema # Verify add_resource was called for each schema
assert mock_mcp.add_resource.call_count == 3 assert mock_mcp.add_resource.call_count == 3
@patch('mcp_cordra.server.cordra_client') @patch('cordra_mcp.server.cordra_client')
async def test_register_schema_resources_missing_name(self, mock_client): async def test_register_schema_resources_missing_name(self, mock_client):
"""Test schema resource registration with objects missing name field.""" """Test schema resource registration with objects missing name field."""
mock_schemas = [ mock_schemas = [
@@ -212,20 +213,20 @@ class TestSchemaResourceFunctions:
] ]
mock_client.find = AsyncMock(return_value=mock_schemas) mock_client.find = AsyncMock(return_value=mock_schemas)
with patch('mcp_cordra.server.mcp') as mock_mcp: with patch('cordra_mcp.server.mcp') as mock_mcp:
from mcp_cordra.server import register_schema_resources from cordra_mcp.server import register_schema_resources
await register_schema_resources() await register_schema_resources()
# Only 2 schemas should be registered (those with name field) # Only 2 schemas should be registered (those with name field)
assert mock_mcp.add_resource.call_count == 2 assert mock_mcp.add_resource.call_count == 2
@patch('mcp_cordra.server.cordra_client') @patch('cordra_mcp.server.cordra_client')
async def test_register_schema_resources_client_error(self, mock_client): async def test_register_schema_resources_client_error(self, mock_client):
"""Test schema resource registration with client error.""" """Test schema resource registration with client error."""
mock_client.find = AsyncMock(side_effect=CordraClientError("Search failed")) mock_client.find = AsyncMock(side_effect=CordraClientError("Search failed"))
# Should not raise an exception, just log a warning # Should not raise an exception, just log a warning
from mcp_cordra.server import register_schema_resources from cordra_mcp.server import register_schema_resources
await register_schema_resources() # Should complete without raising await register_schema_resources() # Should complete without raising
mock_client.find.assert_called_once_with("type:Schema") mock_client.find.assert_called_once_with("type:Schema")

112
uv.lock generated
View File

@@ -111,6 +111,57 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
] ]
[[package]]
name = "cordra-mcp"
version = "0.1.0"
source = { editable = "." }
dependencies = [
{ name = "mcp", extra = ["cli"] },
{ name = "pydantic" },
{ name = "pydantic-settings" },
{ name = "requests" },
]
[package.optional-dependencies]
dev = [
{ name = "loguru" },
{ name = "mypy" },
{ name = "pytest" },
{ name = "pytest-asyncio" },
{ name = "pytest-cov" },
{ name = "ruff" },
]
[package.dev-dependencies]
dev = [
{ name = "mypy" },
{ name = "pytest-asyncio" },
{ name = "ruff" },
{ name = "types-requests" },
]
[package.metadata]
requires-dist = [
{ name = "loguru", marker = "extra == 'dev'", specifier = ">=0.7.0" },
{ name = "mcp", extras = ["cli"], specifier = ">=1.2.0" },
{ name = "mypy", marker = "extra == 'dev'", specifier = ">=1.6.0" },
{ name = "pydantic", specifier = ">=2.0.0" },
{ name = "pydantic-settings", specifier = ">=2.0.0" },
{ name = "pytest", marker = "extra == 'dev'", specifier = ">=7.4.0" },
{ name = "pytest-asyncio", marker = "extra == 'dev'", specifier = ">=0.21.0" },
{ name = "pytest-cov", marker = "extra == 'dev'", specifier = ">=4.1.0" },
{ name = "requests", specifier = ">=2.25.0" },
{ name = "ruff", marker = "extra == 'dev'", specifier = ">=0.1.0" },
]
[package.metadata.requires-dev]
dev = [
{ name = "mypy", specifier = ">=1.16.1" },
{ name = "pytest-asyncio", specifier = ">=1.0.0" },
{ name = "ruff", specifier = ">=0.12.1" },
{ name = "types-requests", specifier = ">=2.32.4.20250611" },
]
[[package]] [[package]]
name = "coverage" name = "coverage"
version = "7.9.1" version = "7.9.1"
@@ -313,55 +364,6 @@ cli = [
{ name = "typer" }, { name = "typer" },
] ]
[[package]]
name = "cordra-mcp"
version = "0.1.0"
source = { editable = "." }
dependencies = [
{ name = "mcp", extra = ["cli"] },
{ name = "pydantic" },
{ name = "pydantic-settings" },
{ name = "requests" },
]
[package.optional-dependencies]
dev = [
{ name = "loguru" },
{ name = "mypy" },
{ name = "pytest" },
{ name = "pytest-asyncio" },
{ name = "pytest-cov" },
{ name = "ruff" },
]
[package.dev-dependencies]
dev = [
{ name = "mypy" },
{ name = "pytest-asyncio" },
{ name = "ruff" },
]
[package.metadata]
requires-dist = [
{ name = "loguru", marker = "extra == 'dev'", specifier = ">=0.7.0" },
{ name = "mcp", extras = ["cli"], specifier = ">=1.2.0" },
{ name = "mypy", marker = "extra == 'dev'", specifier = ">=1.6.0" },
{ name = "pydantic", specifier = ">=2.0.0" },
{ name = "pydantic-settings", specifier = ">=2.0.0" },
{ name = "pytest", marker = "extra == 'dev'", specifier = ">=7.4.0" },
{ name = "pytest-asyncio", marker = "extra == 'dev'", specifier = ">=0.21.0" },
{ name = "pytest-cov", marker = "extra == 'dev'", specifier = ">=4.1.0" },
{ name = "requests", specifier = ">=2.25.0" },
{ name = "ruff", marker = "extra == 'dev'", specifier = ">=0.1.0" },
]
[package.metadata.requires-dev]
dev = [
{ name = "mypy", specifier = ">=1.16.1" },
{ name = "pytest-asyncio", specifier = ">=1.0.0" },
{ name = "ruff", specifier = ">=0.12.1" },
]
[[package]] [[package]]
name = "mdurl" name = "mdurl"
version = "0.1.2" version = "0.1.2"
@@ -840,6 +842,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/76/42/3efaf858001d2c2913de7f354563e3a3a2f0decae3efe98427125a8f441e/typer-0.16.0-py3-none-any.whl", hash = "sha256:1f79bed11d4d02d4310e3c1b7ba594183bcedb0ac73b27a9e5f28f6fb5b98855", size = 46317 }, { url = "https://files.pythonhosted.org/packages/76/42/3efaf858001d2c2913de7f354563e3a3a2f0decae3efe98427125a8f441e/typer-0.16.0-py3-none-any.whl", hash = "sha256:1f79bed11d4d02d4310e3c1b7ba594183bcedb0ac73b27a9e5f28f6fb5b98855", size = 46317 },
] ]
[[package]]
name = "types-requests"
version = "2.32.4.20250611"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "urllib3" },
]
sdist = { url = "https://files.pythonhosted.org/packages/6d/7f/73b3a04a53b0fd2a911d4ec517940ecd6600630b559e4505cc7b68beb5a0/types_requests-2.32.4.20250611.tar.gz", hash = "sha256:741c8777ed6425830bf51e54d6abe245f79b4dcb9019f1622b773463946bf826", size = 23118 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/3d/ea/0be9258c5a4fa1ba2300111aa5a0767ee6d18eb3fd20e91616c12082284d/types_requests-2.32.4.20250611-py3-none-any.whl", hash = "sha256:ad2fe5d3b0cb3c2c902c8815a70e7fb2302c4b8c1f77bdcd738192cdb3878072", size = 20643 },
]
[[package]] [[package]]
name = "typing-extensions" name = "typing-extensions"
version = "4.14.0" version = "4.14.0"