Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@
AsyncQuery,
AsyncTransaction,
AsyncWriteBatch,
BSONBinary,
BSONDecimal128,
BSONInt32,
BSONMaxKey,
BSONMinKey,
BSONObjectID,
BSONRegex,
BSONTimestamp,
Client,
CollectionGroup,
CollectionReference,
Expand Down Expand Up @@ -92,6 +100,14 @@
"async_transactional",
"AsyncTransaction",
"AsyncWriteBatch",
"BSONBinary",
"BSONDecimal128",
"BSONInt32",
"BSONMaxKey",
"BSONMinKey",
"BSONObjectID",
"BSONRegex",
"BSONTimestamp",
"Client",
"CountAggregation",
"CollectionGroup",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@
from google.cloud.firestore_v1.base_pipeline import SubPipeline
from google.cloud.firestore_v1.base_query import And, FieldFilter, Or
from google.cloud.firestore_v1.batch import WriteBatch
from google.cloud.firestore_v1.bson import (
BSONBinary,
BSONDecimal128,
BSONInt32,
BSONMaxKey,
BSONMinKey,
BSONObjectID,
BSONRegex,
BSONTimestamp,
)
from google.cloud.firestore_v1.client import Client
from google.cloud.firestore_v1.collection import CollectionReference
from google.cloud.firestore_v1.document import DocumentReference
Expand Down Expand Up @@ -147,6 +157,14 @@
"async_transactional",
"AsyncTransaction",
"AsyncWriteBatch",
"BSONBinary",
"BSONDecimal128",
"BSONInt32",
"BSONMaxKey",
"BSONMinKey",
"BSONObjectID",
"BSONRegex",
"BSONTimestamp",
"Client",
"CountAggregation",
"CollectionGroup",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import datetime
import json
import re
from typing import (
TYPE_CHECKING,
Any,
Expand All @@ -44,6 +45,13 @@
import google
from google.cloud import exceptions # type: ignore
from google.cloud.firestore_v1 import transforms, types
from google.cloud.firestore_v1.bson import (
BSONBinary,
BSONDecimal128,
BSONObjectID,
BSONRegex,
BSONType,
)
from google.cloud.firestore_v1.field_path import FieldPath, parse_field_path
from google.cloud.firestore_v1.types import common, document, write
from google.cloud.firestore_v1.types.write import DocumentTransform
Expand Down Expand Up @@ -163,13 +171,28 @@ def verify_path(path, is_collection) -> None:
raise ValueError(msg)


def encode_value(value) -> types.document.Value:
"""Converts a native Python value into a Firestore protobuf ``Value``.
_REGEX_FLAG_MAP = (
(re.IGNORECASE, "i"),
(re.MULTILINE, "m"),
(re.DOTALL, "s"),
(re.VERBOSE, "x"),
(re.LOCALE, "l"),
)


def _extract_regex_options(flags: Union[int, str]) -> str:
if isinstance(flags, str):
return flags
if isinstance(flags, int):
return "".join(char for bit, char in _REGEX_FLAG_MAP if flags & bit)
return ""


def encode_value(value: Any) -> document.Value:
"""Convert a Python value into a Value protobuf.

Args:
value (Union[NoneType, bool, int, float, datetime.datetime, \
str, bytes, dict, ~google.cloud.Firestore.GeoPoint, \
~google.cloud.firestore_v1.vector.Vector]): A native
value (Any): The
Python value to convert to a protobuf field.

Returns:
Expand All @@ -182,6 +205,26 @@ def encode_value(value) -> types.document.Value:
if value is None:
return document.Value(null_value=struct_pb2.NULL_VALUE)

if isinstance(value, BSONType):
return encode_value(value.to_map_value())

# Duck-typing input bridge for external PyMongo / bson package objects (zero dependency)
binary_attr = getattr(value, "binary", None)
if binary_attr is not None and not isinstance(
value, (bytes, bytearray, BSONBinary)
):
return encode_value(BSONObjectID(binary_attr))

to_decimal_fn = getattr(value, "to_decimal", None)
if callable(to_decimal_fn) and not isinstance(value, BSONDecimal128):
return encode_value(BSONDecimal128(to_decimal_fn()))

pattern_attr = getattr(value, "pattern", None)
if pattern_attr is not None and not isinstance(value, (str, BSONRegex)):
flags_attr = getattr(value, "flags", "")
options_str = _extract_regex_options(flags_attr)
return encode_value(BSONRegex(pattern_attr, options_str))

# Must come before int since ``bool`` is an integer subtype.
if isinstance(value, bool):
return document.Value(boolean_value=value)
Expand Down
Loading
Loading