feat: Initial version of CleverSwarm Python SDK
/ test (push) Successful in 9m10s

Extend CleverSwarm codebase with PDF and Machine and Worker IDs

ISSUES CLOSED: #1
This commit was merged in pull request #2.
This commit is contained in:
CoreRasurae
2025-09-28 22:21:10 +01:00
committed by Luis Mendes
parent 1aebcfda0f
commit cd808dc3dd
17 changed files with 219 additions and 66 deletions
+20 -23
View File
@@ -111,27 +111,6 @@ class TestCleverSwarmClient:
assert client._timeout == 30
assert client._triplets_template == "custom_{}_output.jsonl"
def test_client_file_operations_with_real_files(self):
"""Test client file operations with real files."""
with tempfile.TemporaryDirectory() as temp_dir:
# Create test files
text_file = Path(temp_dir) / "test.txt"
json_file = Path(temp_dir) / "test.json"
owl_file = Path(temp_dir) / "test.owl"
text_file.write_text("Test content")
json_file.write_text('{"test": "data"}')
owl_file.write_text('<rdf:RDF>test</rdf:RDF>')
# Test that files exist and can be used
assert text_file.exists()
assert json_file.exists()
assert owl_file.exists()
# Test that we can create a client and it recognizes the files
client = CleverSwarmClient("http://localhost:8000/api/v0/")
assert client._base_url == "http://localhost:8000/api/v0/"
def test_file_validation_with_missing_files(self):
"""Test file validation with missing files."""
# Test with non-existent files - this should raise InvalidFileException before calling update_token
@@ -157,10 +136,27 @@ class TestCleverSwarmClient:
json_file.write_text('{"test": "data"}')
jsonl_file.write_text('{"test": "data"}')
# These should not raise exceptions
# Test that files exist and are valid files
assert text_file.exists()
assert text_file.is_file()
assert json_file.exists()
assert json_file.is_file()
assert jsonl_file.exists()
assert jsonl_file.is_file()
# Test that the client can validate these files by calling create_benchmark_job
# We need to mock the update_token and the HTTP request to avoid actual API calls
with patch.object(self.client, 'update_token'):
with patch.object(self.client, '_generic_http_request_executor') as mock_executor:
# Mock the executor to return the job_id directly
mock_executor.return_value = "test_job_123"
# This should not raise InvalidFileException
result = self.client.create_benchmark_job(
text_file, json_file, jsonl_file, True
)
assert result == "test_job_123"
def test_client_state_management(self):
"""Test client state management."""
@@ -273,6 +269,7 @@ class TestCleverSwarmClient:
assert FileTypeAPI.AutoDetect == "AutoDetect"
assert FileTypeAPI.Markdown == "Markdown"
assert FileTypeAPI.PlainText == "PlainText"
assert FileTypeAPI.PDF == "PDF"
def test_response_type_enum_values(self):
"""Test ResponseTypeAPI enum values."""
@@ -850,4 +847,4 @@ class TestCleverSwarmClientHTTP:
raise ValueError("Unexpected error")
with pytest.raises(UnexpectedConditionException):
self.client._generic_http_request_executor(test_func)
self.client._generic_http_request_executor(test_func)
+7 -3
View File
@@ -448,13 +448,15 @@ class TestBenchmarkCLIUtilityMethods:
"type": "Benchmark",
"status": "Completed",
"retries_count": 0,
"file_type": "JSONL"
"file_type": "JSONL",
"machine_id": "machine-001",
"worker_id": "worker-001"
}
]
mock_client.get_jobs_list.return_value = mock_jobs
mock_client_class.return_value = mock_client
self.cli._client = mock_client
self.cli.print_server_jobs()
captured = capsys.readouterr()
@@ -473,6 +475,8 @@ class TestBenchmarkCLIUtilityMethods:
"status": "Completed",
"retries_count": 0,
"file_type": "JSONL",
"machine_id": "machine-001",
"worker_id": "worker-001",
"unstructured_sources": ["test.txt"],
"ontology_sources": ["test.json"],
"ground_truth_sources": ["gt.jsonl"]
@@ -481,7 +485,7 @@ class TestBenchmarkCLIUtilityMethods:
mock_client.get_jobs_list.return_value = mock_jobs
mock_client_class.return_value = mock_client
self.cli._client = mock_client
self.cli.print_server_jobs(detailed=True)
captured = capsys.readouterr()
@@ -60,6 +60,8 @@ class TestBenchmarkCLIExtended:
"status": "Completed",
"retries_count": 0,
"file_type": "JSONL",
"machine_id": "machine-001",
"worker_id": "worker-001",
"unstructured_sources": ["test.txt"],
"ontology_sources": ["test.json"],
"ontology_spec_sources": ["test.owl"],
@@ -67,7 +69,7 @@ class TestBenchmarkCLIExtended:
"ground_truth_sources": ["test_gt.jsonl"]
}
]
with patch.object(self.cli, 'list_server_jobs') as mock_list:
mock_list.return_value = mock_jobs
self.cli.print_server_jobs(detailed=True)
@@ -82,13 +84,15 @@ class TestBenchmarkCLIExtended:
"status": "Completed",
"retries_count": 0,
"file_type": "JSONL",
"machine_id": "machine-001",
"worker_id": "worker-001",
"unstructured_sources": ["test.txt"],
"ontology_sources": ["test.json"],
"ontology_spec_sources": ["test.owl"],
"ground_truth_sources": ["test_gt.jsonl"]
}
]
with patch.object(self.cli, 'list_server_jobs') as mock_list:
mock_list.return_value = mock_jobs
self.cli.print_server_jobs(detailed=True)
+10 -4
View File
@@ -534,11 +534,13 @@ class TestTextoToKGCLIJobPrinting:
"type": "UnstructuredWithOntology",
"status": "Completed",
"retries_count": 0,
"file_type": "JSONL"
"file_type": "JSONL",
"machine_id": "machine-001",
"worker_id": "worker-001"
}
]
mock_list_jobs.return_value = mock_jobs
self.cli.print_server_jobs()
captured = capsys.readouterr()
@@ -556,13 +558,15 @@ class TestTextoToKGCLIJobPrinting:
"status": "Completed",
"retries_count": 0,
"file_type": "JSONL",
"machine_id": "machine-001",
"worker_id": "worker-001",
"unstructured_sources": ["test.txt"],
"ontology_sources": ["test.json"],
"ontology_spec_sources": ["test.owl"]
}
]
mock_list_jobs.return_value = mock_jobs
self.cli.print_server_jobs(is_detailed=True)
captured = capsys.readouterr()
@@ -582,6 +586,8 @@ class TestTextoToKGCLIJobPrinting:
"status": "Completed",
"retries_count": 0,
"file_type": "JSONL",
"machine_id": "machine-001",
"worker_id": "worker-001",
"unstructured_sources": ["test.txt"],
"ontology_sources": ["test.json"],
"ontology_spec_sources": ["test.owl"],
@@ -589,7 +595,7 @@ class TestTextoToKGCLIJobPrinting:
}
]
mock_list_jobs.return_value = mock_jobs
self.cli.print_server_jobs(is_detailed=True)
captured = capsys.readouterr()
@@ -182,13 +182,15 @@ class TestTextoToKGCLIExtended:
"status": "Completed",
"retries_count": 0,
"file_type": "JSONL",
"machine_id": "machine-001",
"worker_id": "worker-001",
"unstructured_sources": ["test.txt"],
"ontology_sources": ["test.json"],
"ontology_spec_sources": ["test.owl"]
}
]
mock_client.get_jobs_list.return_value = mock_jobs
with patch('builtins.print') as mock_print:
self.cli.print_server_jobs()
assert mock_print.call_count > 0
@@ -204,6 +206,8 @@ class TestTextoToKGCLIExtended:
"status": "Completed",
"retries_count": 0,
"file_type": "JSONL",
"machine_id": "machine-001",
"worker_id": "worker-001",
"unstructured_sources": ["test.txt"],
"ontology_sources": ["test.json"],
"ontology_spec_sources": ["test.owl"],
@@ -211,7 +215,7 @@ class TestTextoToKGCLIExtended:
}
]
mock_client.get_jobs_list.return_value = mock_jobs
with patch('builtins.print') as mock_print:
self.cli.print_server_jobs(is_detailed=True)
assert mock_print.call_count > 0
@@ -227,13 +231,15 @@ class TestTextoToKGCLIExtended:
"status": "Completed",
"retries_count": 0,
"file_type": "JSONL",
"machine_id": "machine-001",
"worker_id": "worker-001",
"unstructured_sources": ["test.txt"],
"ontology_sources": ["test.json"],
"ontology_spec_sources": ["test.owl"]
}
]
mock_client.get_jobs_list.return_value = mock_jobs
with patch('builtins.print') as mock_print:
self.cli.print_server_jobs(is_detailed=True)
assert mock_print.call_count > 0
+4 -1
View File
@@ -43,7 +43,10 @@ class TestDetailedEvalExtendedSimple:
encoder = CustomEncoder()
test_set = {1, 2, 3, "test"}
result = encoder.default(test_set)
assert result == [1, 2, 3, "test"]
# Convert result back to set for order-independent comparison
assert set(result) == test_set
# Also verify it's a list
assert isinstance(result, list)
def test_custom_encoder_with_non_set(self):
"""Test CustomEncoder with non-set objects."""
+20 -19
View File
@@ -30,6 +30,7 @@ class TestFileTypeAPI:
assert FileTypeAPI.AutoDetect == "AutoDetect"
assert FileTypeAPI.Markdown == "Markdown"
assert FileTypeAPI.PlainText == "PlainText"
assert FileTypeAPI.PDF == "PDF"
def test_enum_membership(self):
"""Test that FileTypeAPI members can be checked for membership."""
@@ -37,6 +38,7 @@ class TestFileTypeAPI:
assert FileTypeAPI.AutoDetect in FileTypeAPI
assert FileTypeAPI.Markdown in FileTypeAPI
assert FileTypeAPI.PlainText in FileTypeAPI
assert FileTypeAPI.PDF in FileTypeAPI
# Test string value membership (Python 3.12+ only)
import sys
@@ -44,13 +46,14 @@ class TestFileTypeAPI:
assert "AutoDetect" in FileTypeAPI
assert "Markdown" in FileTypeAPI
assert "PlainText" in FileTypeAPI
assert "PDF" in FileTypeAPI
assert "InvalidType" not in FileTypeAPI
def test_enum_iteration(self):
"""Test that FileTypeAPI can be iterated over."""
values = list(FileTypeAPI)
expected_values = ["AutoDetect", "Markdown", "PlainText"]
assert len(values) == 3
expected_values = ["AutoDetect", "Markdown", "PlainText", "PDF"]
assert len(values) == 4
for value in expected_values:
assert value in values
@@ -59,6 +62,7 @@ class TestFileTypeAPI:
assert FileTypeAPI.AutoDetect == "AutoDetect"
assert FileTypeAPI.Markdown == "Markdown"
assert FileTypeAPI.PlainText == "PlainText"
assert FileTypeAPI.PDF == "PDF"
assert FileTypeAPI.AutoDetect != FileTypeAPI.Markdown
def test_enum_string_representation(self):
@@ -66,6 +70,7 @@ class TestFileTypeAPI:
assert str(FileTypeAPI.AutoDetect) == "AutoDetect"
assert str(FileTypeAPI.Markdown) == "Markdown"
assert str(FileTypeAPI.PlainText) == "PlainText"
assert str(FileTypeAPI.PDF) == "PDF"
def test_enum_repr(self):
"""Test repr representation of FileTypeAPI values."""
@@ -73,18 +78,14 @@ class TestFileTypeAPI:
assert "FileTypeAPI.AutoDetect" in repr(FileTypeAPI.AutoDetect)
assert "FileTypeAPI.Markdown" in repr(FileTypeAPI.Markdown)
assert "FileTypeAPI.PlainText" in repr(FileTypeAPI.PlainText)
assert "FileTypeAPI.PDF" in repr(FileTypeAPI.PDF)
def test_enum_inheritance(self):
"""Test that FileTypeAPI inherits from StrEnum."""
from enum import StrEnum
# Import StrEnum from the same module where FileTypeAPI is defined
from cleverswarm_python_client.libs.file_type_enum import StrEnum
assert issubclass(FileTypeAPI, StrEnum)
def test_enum_equality_with_string(self):
"""Test that FileTypeAPI values are equal to their string representations."""
assert FileTypeAPI.AutoDetect == "AutoDetect"
assert FileTypeAPI.Markdown == "Markdown"
assert FileTypeAPI.PlainText == "PlainText"
def test_enum_case_sensitivity(self):
"""Test that FileTypeAPI values are case sensitive."""
assert FileTypeAPI.AutoDetect != "autodetect"
@@ -100,6 +101,7 @@ class TestFileType:
assert FileType.JSONL == "JSONL"
assert FileType.Markdown == "Markdown"
assert FileType.PlainText == "PlainText"
assert FileType.PDF == "PDF"
assert FileType.Unknown == "Unknown"
def test_enum_membership(self):
@@ -108,6 +110,7 @@ class TestFileType:
assert FileType.JSONL in FileType
assert FileType.Markdown in FileType
assert FileType.PlainText in FileType
assert FileType.PDF in FileType
assert FileType.Unknown in FileType
# Test string value membership (Python 3.12+ only)
@@ -116,14 +119,15 @@ class TestFileType:
assert "JSONL" in FileType
assert "Markdown" in FileType
assert "PlainText" in FileType
assert "PDF" in FileType
assert "Unknown" in FileType
assert "InvalidType" not in FileType
def test_enum_iteration(self):
"""Test that FileType can be iterated over."""
values = list(FileType)
expected_values = ["JSONL", "Markdown", "PlainText", "Unknown"]
assert len(values) == 4
expected_values = ["JSONL", "Markdown", "PlainText", "PDF", "Unknown"]
assert len(values) == 5
for value in expected_values:
assert value in values
@@ -132,6 +136,7 @@ class TestFileType:
assert FileType.JSONL == "JSONL"
assert FileType.Markdown == "Markdown"
assert FileType.PlainText == "PlainText"
assert FileType.PDF == "PDF"
assert FileType.Unknown == "Unknown"
assert FileType.JSONL != FileType.Markdown
@@ -140,6 +145,7 @@ class TestFileType:
assert str(FileType.JSONL) == "JSONL"
assert str(FileType.Markdown) == "Markdown"
assert str(FileType.PlainText) == "PlainText"
assert str(FileType.PDF) == "PDF"
assert str(FileType.Unknown) == "Unknown"
def test_enum_repr(self):
@@ -148,20 +154,15 @@ class TestFileType:
assert "FileType.JSONL" in repr(FileType.JSONL)
assert "FileType.Markdown" in repr(FileType.Markdown)
assert "FileType.PlainText" in repr(FileType.PlainText)
assert "FileType.PDF" in repr(FileType.PDF)
assert "FileType.Unknown" in repr(FileType.Unknown)
def test_enum_inheritance(self):
"""Test that FileType inherits from StrEnum."""
from enum import StrEnum
# Import StrEnum from the same module where FileType is defined
from cleverswarm_python_client.libs.file_type_enum import StrEnum
assert issubclass(FileType, StrEnum)
def test_enum_equality_with_string(self):
"""Test that FileType values are equal to their string representations."""
assert FileType.JSONL == "JSONL"
assert FileType.Markdown == "Markdown"
assert FileType.PlainText == "PlainText"
assert FileType.Unknown == "Unknown"
def test_enum_case_sensitivity(self):
"""Test that FileType values are case sensitive."""
assert FileType.JSONL != "jsonl"
+4 -2
View File
@@ -76,7 +76,8 @@ class TestJobType:
def test_enum_inheritance(self):
"""Test that JobType inherits from StrEnum."""
from enum import StrEnum
# Import StrEnum from the same module where JobType is defined
from cleverswarm_python_client.libs.job_enums import StrEnum
assert issubclass(JobType, StrEnum)
def test_enum_equality_with_string(self):
@@ -165,7 +166,8 @@ class TestJobStatus:
def test_enum_inheritance(self):
"""Test that JobStatus inherits from StrEnum."""
from enum import StrEnum
# Import StrEnum from the same module where JobStatus is defined
from cleverswarm_python_client.libs.job_enums import StrEnum
assert issubclass(JobStatus, StrEnum)
def test_enum_equality_with_string(self):
+2 -1
View File
@@ -70,7 +70,8 @@ class TestResponseTypeAPI:
def test_enum_inheritance(self):
"""Test that ResponseTypeAPI inherits from StrEnum."""
from enum import StrEnum
# Import StrEnum from the same module where ResponseTypeAPI is defined
from cleverswarm_python_client.libs.response_type_enum import StrEnum
assert issubclass(ResponseTypeAPI, StrEnum)
def test_enum_equality_with_string(self):