diff --git a/awswrangler/neptune/_neptune.py b/awswrangler/neptune/_neptune.py index e9beb7295..4c262ada0 100644 --- a/awswrangler/neptune/_neptune.py +++ b/awswrangler/neptune/_neptune.py @@ -110,7 +110,12 @@ def execute_sparql(client: NeptuneClient, query: str) -> pd.DataFrame: df = None if "results" in data and "bindings" in data["results"]: df = pd.DataFrame(data["results"]["bindings"], columns=data.get("head", {}).get("vars")) - df = df.applymap(lambda d: d["value"] if "value" in d else None) + + def _binding_value(d: Any) -> Any: + return d.get("value") if isinstance(d, dict) else None + + for col in df.columns: + df[col] = df[col].apply(_binding_value) else: df = pd.DataFrame(data) diff --git a/tests/unit/test_neptune.py b/tests/unit/test_neptune.py index d7236c3fa..77509491c 100644 --- a/tests/unit/test_neptune.py +++ b/tests/unit/test_neptune.py @@ -471,6 +471,51 @@ def test_sparql_write_triples(neptune_endpoint, neptune_port) -> dict[str, Any]: assert len(batch_df.index) == len(final_df.index) + 50 +def test_sparql_bindings_nan_safe() -> None: + class _DummyClient: + def read_sparql(self, _query: str) -> dict[str, Any]: + return { + "head": {"vars": ["book_id", "title", "checked_out", "last_updated", "category_code"]}, + "results": { + "bindings": [ + { + "title": { + "xml:lang": "en", + "type": "literal", + "value": "The Art of Space Travel", + }, + "book_id": {"type": "literal", "value": "B10045982"}, + "last_updated": { + "datatype": "http://www.w3.org/2001/XMLSchema#dateTime", + "type": "literal", + "value": "2025-10-01T10:30:00.000Z", + }, + "category_code": { + "datatype": "http://www.w3.org/2001/XMLSchema#integer", + "type": "literal", + "value": "5", + }, + }, + ] + }, + } + + client: Any = _DummyClient() + df = wr.neptune.execute_sparql( + client, + "SELECT ?book_id ?title ?checked_out ?last_updated ?category_code WHERE { ?s ?p ?o }", + ) + assert df.shape == (1, 5) + # Row 1 + v1 = df.iloc[0].tolist() + book_id, title, checked_out, last_updated, category_code = v1 + assert book_id == "B10045982" + assert title == "The Art of Space Travel" + assert checked_out is None # missing binding becomes None + assert last_updated == "2025-10-01T10:30:00.000Z" + assert category_code == "5" + + def test_sparql_write_quads(neptune_endpoint, neptune_port) -> dict[str, Any]: label = f"foo_{uuid.uuid4()}" sparkql_query = f"SELECT ?p ?o FROM WHERE {{ <{label}> ?p ?o .}}"