This is an automated email from the ASF dual-hosted git repository.
shahar1 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new 80e7e9b0381 Fix Neo4jOperator templated query validation (#70348)
80e7e9b0381 is described below
commit 80e7e9b03817c8487e183fef0f891351991040e8
Author: fat-catTW <[email protected]>
AuthorDate: Fri Jul 24 16:13:49 2026 +0800
Fix Neo4jOperator templated query validation (#70348)
---
.../src/airflow/providers/neo4j/operators/neo4j.py | 18 +++++++++++-------
.../neo4j/tests/unit/neo4j/operators/test_neo4j.py | 20 ++++++++++++--------
.../ci/prek/validate_operators_init_exemptions.txt | 1 -
3 files changed, 23 insertions(+), 16 deletions(-)
diff --git a/providers/neo4j/src/airflow/providers/neo4j/operators/neo4j.py
b/providers/neo4j/src/airflow/providers/neo4j/operators/neo4j.py
index 170204288a8..0c2a6538ad4 100644
--- a/providers/neo4j/src/airflow/providers/neo4j/operators/neo4j.py
+++ b/providers/neo4j/src/airflow/providers/neo4j/operators/neo4j.py
@@ -63,16 +63,20 @@ class Neo4jOperator(BaseOperator):
AirflowProviderDeprecationWarning,
stacklevel=2,
)
- if cypher is not None:
- raise ValueError("Cannot provide both `sql` and `cypher`. Use
`cypher` only.")
- cypher = sql
- if cypher is None:
- raise ValueError("Parameter `cypher` is required.")
self.neo4j_conn_id = neo4j_conn_id
self.cypher = cypher
+ self.sql = sql
self.parameters = parameters
def execute(self, context: Context) -> None:
- self.log.info("Executing: %s", self.cypher)
+ cypher = self.cypher
+ if self.sql is not None:
+ if cypher is not None:
+ raise ValueError("Cannot provide both `sql` and `cypher`. Use
`cypher` only.")
+ cypher = self.render_template(self.sql, context)
+ if cypher is None:
+ raise ValueError("Parameter `cypher` is required.")
+
+ self.log.info("Executing: %s", cypher)
hook = Neo4jHook(conn_id=self.neo4j_conn_id)
- hook.run(self.cypher, self.parameters)
+ hook.run(cypher, self.parameters)
diff --git a/providers/neo4j/tests/unit/neo4j/operators/test_neo4j.py
b/providers/neo4j/tests/unit/neo4j/operators/test_neo4j.py
index fb75adc3faa..3cebcfaffcb 100644
--- a/providers/neo4j/tests/unit/neo4j/operators/test_neo4j.py
+++ b/providers/neo4j/tests/unit/neo4j/operators/test_neo4j.py
@@ -61,16 +61,20 @@ class TestNeo4jOperator:
AirflowProviderDeprecationWarning,
match="`sql` parameter is deprecated, please use `cypher`
instead.",
):
- op = Neo4jOperator(task_id="basic_neo4j", sql=cypher)
- assert op.cypher == cypher
- op.execute(mock.MagicMock())
+ op = Neo4jOperator(task_id="basic_neo4j", sql="{{ cypher }}")
+ assert op.sql == "{{ cypher }}"
+ op.execute({"cypher": cypher})
mock_hook.return_value.run.assert_called_once_with(cypher, None)
- def test_neo4j_operator_both_sql_and_cypher_raises(self):
+ def test_neo4j_operator_both_sql_and_cypher_raises_on_execute(self):
with pytest.warns(AirflowProviderDeprecationWarning):
- with pytest.raises(ValueError, match="Cannot provide both `sql`
and `cypher`"):
- Neo4jOperator(task_id="basic_neo4j", sql="a", cypher="b")
+ op = Neo4jOperator(task_id="basic_neo4j", sql="a", cypher="b")
+
+ with pytest.raises(ValueError, match="Cannot provide both `sql` and
`cypher`"):
+ op.execute(mock.MagicMock())
+
+ def test_neo4j_operator_missing_cypher_raises_on_execute(self):
+ op = Neo4jOperator(task_id="basic_neo4j")
- def test_neo4j_operator_missing_cypher_raises(self):
with pytest.raises(ValueError, match="Parameter `cypher` is
required."):
- Neo4jOperator(task_id="basic_neo4j")
+ op.execute(mock.MagicMock())
diff --git a/scripts/ci/prek/validate_operators_init_exemptions.txt
b/scripts/ci/prek/validate_operators_init_exemptions.txt
index 2f3a91c6b04..db9e1ad7ce8 100644
--- a/scripts/ci/prek/validate_operators_init_exemptions.txt
+++ b/scripts/ci/prek/validate_operators_init_exemptions.txt
@@ -64,7 +64,6 @@
providers/google/src/airflow/providers/google/marketing_platform/operators/campa
providers/microsoft/azure/src/airflow/providers/microsoft/azure/transfers/gcs_to_wasb.py::GCSToAzureBlobStorageOperator
providers/microsoft/azure/src/airflow/providers/microsoft/azure/transfers/oracle_to_azure_data_lake.py::OracleToAzureDataLakeOperator
providers/microsoft/psrp/src/airflow/providers/microsoft/psrp/operators/psrp.py::PsrpOperator
-providers/neo4j/src/airflow/providers/neo4j/operators/neo4j.py::Neo4jOperator
providers/oracle/src/airflow/providers/oracle/transfers/oracle_to_oracle.py::OracleToOracleOperator
providers/papermill/src/airflow/providers/papermill/operators/papermill.py::PapermillOperator
providers/ssh/src/airflow/providers/ssh/operators/ssh.py::SSHOperator