Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
54c4f6e
fixed tests
daniel-sanche Oct 23, 2025
107e412
added vector expressions
daniel-sanche Oct 23, 2025
a0c36ca
added new math expressions
daniel-sanche Oct 24, 2025
dcd6af1
added string manipulation expressions
daniel-sanche Oct 24, 2025
71308dc
added not_nan, not_null, and is_absent
daniel-sanche Oct 24, 2025
0260014
added new Array type
daniel-sanche Oct 24, 2025
1b69435
added map and related expressions
daniel-sanche Oct 24, 2025
be749e0
remove dict and list from constant types
daniel-sanche Oct 24, 2025
789f29c
Fixed lint
daniel-sanche Oct 25, 2025
64be10d
added count_if and count_distinct
daniel-sanche Oct 27, 2025
5d4f878
added misc expressions
daniel-sanche Oct 27, 2025
6d6c57f
added error functions
daniel-sanche Oct 27, 2025
f1690d8
fixed lint
daniel-sanche Oct 27, 2025
86ad143
improved e2e tests
daniel-sanche Oct 28, 2025
f2697ca
fixed broken stages
daniel-sanche Oct 28, 2025
d18e1f9
added options to generic stage
daniel-sanche Oct 28, 2025
68b9eff
fixed unit tests
daniel-sanche Oct 28, 2025
9b2cc6b
ran blacken
daniel-sanche Oct 28, 2025
3ebdb13
broke out aggregates
daniel-sanche Oct 28, 2025
a951789
broke up test file
daniel-sanche Oct 28, 2025
1d48d4d
removed duplicates
daniel-sanche Oct 28, 2025
390ea72
added math file
daniel-sanche Oct 28, 2025
7c2f41f
renamed tests
daniel-sanche Oct 28, 2025
41ff06d
include test file in test name
daniel-sanche Oct 28, 2025
d1dc233
fixed lint
daniel-sanche Oct 28, 2025
ca2caa9
broke out tests into multiple yaml files
daniel-sanche Oct 28, 2025
7425832
fixed static function access
daniel-sanche Oct 28, 2025
086c3af
ignore upgrade warning
daniel-sanche Oct 28, 2025
b46dc66
Merge branch 'pipeline_queries_approved' into pipeline_queries_improv…
daniel-sanche Oct 29, 2025
7059435
skip pipeline verification on kokoro
daniel-sanche Oct 29, 2025
52e11bf
fixed lint
daniel-sanche Oct 29, 2025
c994ad6
fixed test coverage
daniel-sanche Oct 29, 2025
c2abb91
skip all enterprise mode RunQuery tests on kokoro
daniel-sanche Oct 29, 2025
fc09c1c
simplified kokoro check
daniel-sanche Oct 30, 2025
7a4c978
fixed e2e tests
daniel-sanche Oct 30, 2025
3e555da
removed background thread pipeline verifies
daniel-sanche Oct 30, 2025
cddf28b
fixed lint
daniel-sanche Oct 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 16 additions & 12 deletions google/cloud/firestore_v1/_pipeline_stages.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,13 @@ class UnnestOptions:
storing the original 0-based index of the element within the array.
"""

def __init__(self, index_field: str):
self.index_field = index_field
def __init__(self, index_field: Field | str):
self.index_field = (
index_field if isinstance(index_field, Field) else Field.of(index_field)
)

def __repr__(self):
return f"{self.__class__.__name__}(index_field={self.index_field!r})"
return f"{self.__class__.__name__}(index_field={self.index_field.path!r})"


class Stage(ABC):
Expand Down Expand Up @@ -258,13 +260,7 @@ def of(*documents: "BaseDocumentReference") -> "Documents":
return Documents(*doc_paths)

def _pb_args(self):
return [
Value(
array_value={
"values": [Value(string_value=path) for path in self.paths]
}
)
]
return [Value(reference_value=path) for path in self.paths]


class FindNearest(Stage):
Expand Down Expand Up @@ -306,15 +302,23 @@ def _pb_options(self) -> dict[str, Value]:
class GenericStage(Stage):
"""Represents a generic, named stage with parameters."""

def __init__(self, name: str, *params: Expr | Value):
def __init__(
self, name: str, *params: Expr | Value, options: dict[str, Expr | Value] = {}
):
super().__init__(name)
self.params: list[Value] = [
p._to_pb() if isinstance(p, Expr) else p for p in params
]
self.options: dict[str, Value] = {
k: v._to_pb() if isinstance(v, Expr) else v for k, v in options.items()
}

def _pb_args(self):
return self.params

def _pb_options(self):
return self.options

def __repr__(self):
return f"{self.__class__.__name__}(name='{self.name}')"

Expand Down Expand Up @@ -437,7 +441,7 @@ def _pb_args(self):
def _pb_options(self):
options = {}
if self.options is not None:
options["index_field"] = Value(string_value=self.options.index_field)
options["index_field"] = self.options.index_field._to_pb()
return options


Expand Down
8 changes: 3 additions & 5 deletions google/cloud/firestore_v1/pipeline_expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,6 @@ def _to_pb(self) -> Value:
@staticmethod
def _cast_to_expr_or_convert_to_constant(o: Any, include_vector=False) -> "Expr":
"""Convert arbitrary object to an Expr."""
if isinstance(o, Constant) and isinstance(o.value, list):
o = o.value
if isinstance(o, Expr):
return o
if isinstance(o, dict):
Expand Down Expand Up @@ -143,7 +141,7 @@ def __init__(self, instance_func):
def static_func(self, first_arg, *other_args, **kwargs):
if not isinstance(first_arg, (Expr, str)):
raise TypeError(
f"`expressions must be called on an Expr or a string representing a field name. got {type(first_arg)}."
f"'{self.instance_func.__name__}' must be called on an Expression or a string representing a field. got {type(first_arg)}."
)
first_expr = (
Field.of(first_arg) if not isinstance(first_arg, Expr) else first_arg
Expand All @@ -152,7 +150,7 @@ def static_func(self, first_arg, *other_args, **kwargs):

def __get__(self, instance, owner):
if instance is None:
return self.static_func.__get__(instance, owner)
return self.static_func
else:
return self.instance_func.__get__(instance, owner)

Expand Down Expand Up @@ -1280,7 +1278,7 @@ def map_get(self, key: str | Constant[str]) -> "Expr":

@expose_as_static
def map_remove(self, key: str | Constant[str]) -> "Expr":
"""Remove a key from the map produced by evaluating this expression.
"""Remove a key from a the map produced by evaluating this expression.

Example:
>>> Map({"city": "London"}).map_remove("city")
Expand Down
3 changes: 2 additions & 1 deletion pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ filterwarnings =
ignore:.*The \`credentials_file\` argument is deprecated.*:DeprecationWarning
# Remove after updating test dependencies that use asyncio.iscoroutinefunction
ignore:.*\'asyncio.iscoroutinefunction\' is deprecated.*:DeprecationWarning
ignore:.*\'asyncio.get_event_loop_policy\' is deprecated.*:DeprecationWarning
ignore:.*\'asyncio.get_event_loop_policy\' is deprecated.*:DeprecationWarning
ignore:.*Please upgrade to the latest Python version.*:FutureWarning
Loading