diff --git a/src/cleverswarm_python_client/cswarm_text_to_kg_client.py b/src/cleverswarm_python_client/cswarm_text_to_kg_client.py
index 184e041..47a433c 100644
--- a/src/cleverswarm_python_client/cswarm_text_to_kg_client.py
+++ b/src/cleverswarm_python_client/cswarm_text_to_kg_client.py
@@ -76,7 +76,10 @@ class TextoToKGCLI(object):
force_filetype: FileTypeAPI = FileTypeAPI.AutoDetect,
):
input_text_path: Path = self._input_prefix / input_text
- ontology_json_path: Path = self._input_prefix / ontology_json
+ # Ontology JSON file is optional - only create path if it was provided
+ ontology_json_path: Path | None = (
+ self._input_prefix / ontology_json if ontology_json else None
+ )
ontology_owl_path: Path = self._input_prefix / ontology_owl
wildcards_path: Path = Path(wildcards) if wildcards else None
@@ -85,11 +88,15 @@ class TextoToKGCLI(object):
f"Unstructured input text does not exist or is not a file: {str(input_text_path)}"
)
- if not ontology_json_path.exists() or not ontology_json_path.is_file():
+ # If ontology_json was provided, validate that the file exists
+ if ontology_json and ontology_json_path and (not ontology_json_path.exists() or not ontology_json_path.is_file()):
raise ClientException(
- f"Input ontology JSON file does not exist or is not a file: {str(ontology_json_path)}"
+ f"Specified optional Ontology JSON file does not exist or is not a file: {str(ontology_json_path)}"
)
+ # Ontology JSON file is optional - use the path if it was provided and exists
+ ontology_json_path_final: Path | None = ontology_json_path
+
if not ontology_owl_path.exists() or not ontology_owl_path.is_file():
raise ClientException(
f"Input ontology OWL file does not exist or is not a file: {str(ontology_owl_path)}"
@@ -106,7 +113,7 @@ class TextoToKGCLI(object):
if wildcards_job:
job_id: str = self._client.create_unstructured_to_kg_wildcards_job(
input_text_path,
- ontology_json_path,
+ ontology_json_path_final,
ontology_owl_path,
wildcards_path,
force_filetype=force_filetype,
@@ -114,7 +121,7 @@ class TextoToKGCLI(object):
else:
job_id: str = self._client.create_unstructured_to_kg_job(
input_text_path,
- ontology_json_path,
+ ontology_json_path_final,
ontology_owl_path,
force_filetype=force_filetype,
)
@@ -272,7 +279,7 @@ def main():
parser.add_argument(
"--ontology_json",
type=str,
- help="Enriched ontology file with descriptions in JSON format",
+ help="Optional enriched ontology file with descriptions in JSON format",
)
parser.add_argument(
"--ontology_owl",
@@ -306,10 +313,6 @@ def main():
print("create-and-exit action requires --unstructured_text argument.\n")
parser.print_help()
exit(-1)
- if args.ontology_json is None:
- print("create-and-exit action requires --ontology_json argument.\n")
- parser.print_help()
- exit(-1)
if args.ontology_owl is None:
print("create-and-exit action requires --ontology_owl argument.\n")
parser.print_help()
@@ -339,12 +342,6 @@ def main():
)
parser.print_help()
exit(-1)
- if args.ontology_json is None:
- print(
- "create-download-kg-delete action requires --ontology_json argument.\n"
- )
- parser.print_help()
- exit(-1)
if args.ontology_owl is None:
print(
"create-download-kg-delete action requires --ontology_owl argument.\n"
@@ -361,12 +358,6 @@ def main():
)
parser.print_help()
exit(-1)
- if args.ontology_json is None:
- print(
- "create-download-kg-delete action requires --ontology_json argument.\n"
- )
- parser.print_help()
- exit(-1)
if args.ontology_owl is None:
print(
"create-download-kg-delete action requires --ontology_owl argument.\n"
diff --git a/src/cleverswarm_python_client/libs/cleverswarm_client.py b/src/cleverswarm_python_client/libs/cleverswarm_client.py
index 6fe5d43..48ade94 100644
--- a/src/cleverswarm_python_client/libs/cleverswarm_client.py
+++ b/src/cleverswarm_python_client/libs/cleverswarm_client.py
@@ -595,7 +595,7 @@ class CleverSwarmClient(object):
def create_unstructured_to_kg_job(
self,
unstructured_text_file: Path,
- ontology_file: Path,
+ ontology_file: Path | None,
ontology_spec_file: Path,
force_filetype: FileTypeAPI = FileTypeAPI.AutoDetect,
):
@@ -604,7 +604,7 @@ class CleverSwarmClient(object):
Login is requested if required by the server.
If the upload is successful, it returns a job ID.
:param unstructured_text_file: a valid file path containing unstructured text for conversion
- :param ontology_file: a valid file containing an ontology in JSON format.
+ :param ontology_file: optional file containing an ontology in JSON format.
:param ontology_spec_file: a valid file path containing the ontology spec in OWL/XML format.
:param force_filetype: indicate the file type to force for the input file
:return: the job ID where the files were placed.
@@ -618,11 +618,6 @@ class CleverSwarmClient(object):
f"{str(unstructured_text_file)}"
)
- if not ontology_file.exists() or not ontology_file.is_file():
- raise InvalidFileException(
- f"Ontology files does not exist or is not a file: {str(ontology_file)}"
- )
-
if not ontology_spec_file.exists() or not ontology_spec_file.is_file():
raise InvalidFileException(
f"OWL/XML ontology file does not exist or is not a file: "
@@ -634,11 +629,14 @@ class CleverSwarmClient(object):
params = {"file_type": force_filetype}
files = [
("unstructured", open(unstructured_text_file, "rb")),
- ("ontology", open(ontology_file, "rb")),
("ontology_spec", open(ontology_spec_file, "rb")),
]
+ if ontology_file:
+ files.append(("ontology", open(ontology_file, "rb")))
+
response = requests.post(
- self._base_url + "unstructured/with_ontology",
+ self._base_url + ("unstructured/with_ontology" if ontology_file else
+ "unstructured/with_ontology_simple"),
headers=headers,
params=params,
files=files,
@@ -669,7 +667,7 @@ class CleverSwarmClient(object):
def create_unstructured_to_kg_wildcards_job(
self,
unstructured_text_file: Path,
- ontology_file: Path,
+ ontology_file: Path | None,
ontology_spec_file: Path,
wildcards_query_file: Path,
force_filetype: FileTypeAPI = FileTypeAPI.AutoDetect,
@@ -679,7 +677,7 @@ class CleverSwarmClient(object):
Login is requested if required by the server.
If the upload is successful, it returns a job ID.
:param unstructured_text_file: a valid file path containing unstructured text for conversion
- :param ontology_file: a valid file containing an ontology in JSON format.
+ :param ontology_file: optional file containing an ontology in JSON format.
:param ontology_spec_file: a valid file path containing the ontology spec in OWL/XML format.
:param wildcards_query_file: a valid file path containing wildcard queries in JSON.
:param force_filetype: indicate the file type to force for the input file
@@ -694,11 +692,6 @@ class CleverSwarmClient(object):
f"{str(unstructured_text_file)}"
)
- if not ontology_file.exists() or not ontology_file.is_file():
- raise InvalidFileException(
- f"Ontology files does not exist or is not a file: {str(ontology_file)}"
- )
-
if not ontology_spec_file.exists() or not ontology_spec_file.is_file():
raise InvalidFileException(
f"OWL/XML ontology file does not exist or is not a file: "
@@ -716,12 +709,15 @@ class CleverSwarmClient(object):
params = {"file_type": force_filetype}
files = [
("unstructured", open(unstructured_text_file, "rb")),
- ("ontology", open(ontology_file, "rb")),
("ontology_spec", open(ontology_spec_file, "rb")),
("wildcards", open(wildcards_query_file, "rb")),
]
+ if ontology_file:
+ files.append(("ontology", open(ontology_file, "rb")))
+
response = requests.post(
- self._base_url + "unstructured/with_wildcards",
+ self._base_url + ("unstructured/with_wildcards" if ontology_file else
+ "unstructured/with_wildcards_simple"),
headers=headers,
params=params,
files=files,
diff --git a/tests/test_cswarm_text_to_kg_client.py b/tests/test_cswarm_text_to_kg_client.py
index 94fedbe..6d58387 100644
--- a/tests/test_cswarm_text_to_kg_client.py
+++ b/tests/test_cswarm_text_to_kg_client.py
@@ -214,18 +214,75 @@ class TestTextoToKGCLIJobCreation:
"test.owl"
)
- def test_create_job_invalid_json_file(self):
- """Test job creation with invalid JSON file."""
+ def test_create_job_with_invalid_json_file(self):
+ """Test job creation with invalid (non-existent) JSON file - should raise exception if JSON is provided."""
with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as text_file:
text_file.write("Test text content")
text_file.flush()
- with pytest.raises(ClientException, match="Input ontology JSON file does not exist"):
- self.cli.create_job(
- text_file.name,
- "nonexistent.json",
- "test.owl"
- )
+ with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.owl') as owl_file:
+ owl_file.write('test')
+ owl_file.flush()
+
+ # If ontology_json is provided but file doesn't exist, should raise exception
+ with pytest.raises(ClientException, match="Specified optional Ontology JSON file does not exist"):
+ self.cli.create_job(
+ text_file.name,
+ "nonexistent.json", # Non-existent JSON file - should raise exception
+ owl_file.name
+ )
+
+ def test_create_job_without_json_file(self):
+ """Test job creation without JSON file - should work since JSON is optional."""
+ with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as text_file:
+ text_file.write("Test text content")
+ text_file.flush()
+
+ with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.owl') as owl_file:
+ owl_file.write('test')
+ owl_file.flush()
+
+ with patch.object(self.cli._client, 'create_unstructured_to_kg_job') as mock_create:
+ mock_create.return_value = "test_job_123"
+
+ # Job creation should work without JSON file since it's optional
+ result = self.cli.create_job(
+ text_file.name,
+ None, # No JSON file provided - should work
+ owl_file.name
+ )
+
+ assert result == "test_job_123"
+ mock_create.assert_called_once()
+ # Verify that None was passed for ontology_file since it wasn't provided
+ call_args = mock_create.call_args
+ assert call_args[0][1] is None # ontology_file parameter should be None
+
+ def test_create_job_with_empty_json_file_string(self):
+ """Test job creation with empty string for JSON file - should work since JSON is optional."""
+ with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as text_file:
+ text_file.write("Test text content")
+ text_file.flush()
+
+ with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.owl') as owl_file:
+ owl_file.write('test')
+ owl_file.flush()
+
+ with patch.object(self.cli._client, 'create_unstructured_to_kg_job') as mock_create:
+ mock_create.return_value = "test_job_123"
+
+ # Job creation should work with empty string for JSON file since it's optional
+ result = self.cli.create_job(
+ text_file.name,
+ "", # Empty string for JSON file - should work
+ owl_file.name
+ )
+
+ assert result == "test_job_123"
+ mock_create.assert_called_once()
+ # Verify that None was passed for ontology_file since empty string is falsy
+ call_args = mock_create.call_args
+ assert call_args[0][1] is None # ontology_file parameter should be None
def test_create_job_invalid_owl_file(self):
"""Test job creation with invalid OWL file."""