diff --git a/packages/google-cloud-firestore/google/cloud/firestore_v1/base_pipeline.py b/packages/google-cloud-firestore/google/cloud/firestore_v1/base_pipeline.py index fac7f8bc4bce..df6096f08261 100644 --- a/packages/google-cloud-firestore/google/cloud/firestore_v1/base_pipeline.py +++ b/packages/google-cloud-firestore/google/cloud/firestore_v1/base_pipeline.py @@ -459,7 +459,12 @@ def unnest( """ return self._append(stages.Unnest(field, alias, options)) - def raw_stage(self, name: str, *params: Expression) -> "_BasePipeline": + def raw_stage( + self, + name: str, + *params: Expression, + options: dict[str, Expression | Value] | None = None, + ) -> "_BasePipeline": """ Adds a stage to the pipeline by specifying the stage name as an argument. This does not offer any type safety on the stage params and requires the caller to know the order (and optionally names) @@ -477,11 +482,12 @@ def raw_stage(self, name: str, *params: Expression) -> "_BasePipeline": Args: name: The name of the stage. *params: A sequence of `Expression` objects representing the parameters for the stage. + options: An optional dictionary of stage options. Returns: A new Pipeline object with this stage appended to the stage list """ - return self._append(stages.RawStage(name, *params)) + return self._append(stages.RawStage(name, *params, options=options or {})) def offset(self, offset: int) -> "_BasePipeline": """ diff --git a/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_expressions.py b/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_expressions.py index 969ddf2794a5..74ac21542fb8 100644 --- a/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_expressions.py +++ b/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_expressions.py @@ -11,11 +11,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" -.. warning:: - **Preview API**: Firestore Pipelines is currently in preview and is - subject to potential breaking changes in future releases. -""" from __future__ import annotations @@ -188,7 +183,7 @@ class Expression(ABC): """Represents an expression that can be evaluated to a value within the execution of a pipeline. - Expressionessions are the building blocks for creating complex queries and + Expressions are the building blocks for creating complex queries and transformations in Firestore pipelines. They can represent: - **Field references:** Access values from document fields. @@ -938,7 +933,7 @@ def is_absent(self) -> "BooleanExpression": >>> Field.of("email").is_absent() Returns: - A new `BooleanExpressionession` representing the isAbsent operation. + A new `BooleanExpression` representing the isAbsent operation. """ return BooleanExpression("is_absent", [self]) @@ -1832,10 +1827,6 @@ def array_agg(self) -> "Expression": `None`. The order of elements in the output array is not stable and shouldn't be relied upon. - This API is provided as a preview for developers and may change based - on feedback that we receive. Do not use this API in a production - environment. - Example: >>> # Collect all values of field 'color' into an array >>> Field.of("color").array_agg() @@ -1854,10 +1845,6 @@ def array_agg_distinct(self) -> "Expression": `None`. The order of elements in the output array is not stable and shouldn't be relied upon. - This API is provided as a preview for developers and may change based - on feedback that we receive. Do not use this API in a production - environment. - Example: >>> # Collect distinct values of field 'color' into an array >>> Field.of("color").array_agg_distinct() @@ -1872,10 +1859,6 @@ def first(self) -> "Expression": """Creates an aggregation that finds the first value of an expression across multiple stage inputs. - This API is provided as a preview for developers and may change based - on feedback that we receive. Do not use this API in a production - environment. - Example: >>> # Select the first value of field 'color' >>> Field.of("color").first() @@ -1890,10 +1873,6 @@ def last(self) -> "Expression": """Creates an aggregation that finds the last value of an expression across multiple stage inputs. - This API is provided as a preview for developers and may change based - on feedback that we receive. Do not use this API in a production - environment. - Example: >>> # Select the last value of field 'color' >>> Field.of("color").last() diff --git a/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_result.py b/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_result.py index 432c1dd8206d..6de085fcc7ce 100644 --- a/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_result.py +++ b/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_result.py @@ -11,11 +11,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" -.. warning:: - **Preview API**: Firestore Pipelines is currently in preview and is - subject to potential breaking changes in future releases. -""" from __future__ import annotations diff --git a/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_source.py b/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_source.py index 7075797b3d57..f2a8b23bcc38 100644 --- a/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_source.py +++ b/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_source.py @@ -11,11 +11,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" -.. warning:: - **Preview API**: Firestore Pipelines is currently in preview and is - subject to potential breaking changes in future releases. -""" from __future__ import annotations diff --git a/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_stages.py b/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_stages.py index cac9c70d4b99..6f29657701b3 100644 --- a/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_stages.py +++ b/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_stages.py @@ -11,11 +11,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -""" -.. warning:: - **Preview API**: Firestore Pipelines is currently in preview and is - subject to potential breaking changes in future releases. -""" from __future__ import annotations diff --git a/packages/google-cloud-firestore/tests/unit/v1/test_async_pipeline.py b/packages/google-cloud-firestore/tests/unit/v1/test_async_pipeline.py index 4059355c687d..0dfee04f4e82 100644 --- a/packages/google-cloud-firestore/tests/unit/v1/test_async_pipeline.py +++ b/packages/google-cloud-firestore/tests/unit/v1/test_async_pipeline.py @@ -448,3 +448,17 @@ def test_async_pipeline_aggregate_with_groups(): assert isinstance(result_ppl.stages[0], stages.Aggregate) assert list(result_ppl.stages[0].groups) == [Field.of("author")] assert list(result_ppl.stages[0].accumulators) == [Field.of("title")] + + +def test_async_pipeline_raw_stage_with_options(): + from google.cloud.firestore_v1.base_vector_query import Field + from google.cloud.firestore_v1.pipeline_stages import RawStage + + start_ppl = _make_async_pipeline() + result_ppl = start_ppl.raw_stage( + "stage_name", Field.of("n"), options={"key": "val"} + ) + assert len(start_ppl.stages) == 0 + assert len(result_ppl.stages) == 1 + assert isinstance(result_ppl.stages[0], RawStage) + assert result_ppl.stages[0].options == {"key": "val"} diff --git a/packages/google-cloud-firestore/tests/unit/v1/test_pipeline.py b/packages/google-cloud-firestore/tests/unit/v1/test_pipeline.py index 5953398709a3..8423c67ea095 100644 --- a/packages/google-cloud-firestore/tests/unit/v1/test_pipeline.py +++ b/packages/google-cloud-firestore/tests/unit/v1/test_pipeline.py @@ -437,3 +437,17 @@ def test_pipeline_aggregate_with_groups(): assert isinstance(result_ppl.stages[0], stages.Aggregate) assert list(result_ppl.stages[0].groups) == [Field.of("author")] assert list(result_ppl.stages[0].accumulators) == [Field.of("title")] + + +def test_pipeline_raw_stage_with_options(): + from google.cloud.firestore_v1.base_vector_query import Field + from google.cloud.firestore_v1.pipeline_stages import RawStage + + start_ppl = _make_pipeline() + result_ppl = start_ppl.raw_stage( + "stage_name", Field.of("n"), options={"key": "val"} + ) + assert len(start_ppl.stages) == 0 + assert len(result_ppl.stages) == 1 + assert isinstance(result_ppl.stages[0], RawStage) + assert result_ppl.stages[0].options == {"key": "val"}