def convert_precondition(precond): from google.cloud.firestore_v1 import Client if precond.HasField("exists"): return Client.write_option(exists=precond.exists) assert precond.HasField("update_time") return Client.write_option(last_update_time=precond.update_time)
def _make_client_document(firestore_api, testcase): from google.cloud.firestore_v1 import Client from google.cloud.firestore_v1.client import DEFAULT_DATABASE import google.auth.credentials _, project, _, database, _, doc_path = testcase.doc_ref_path.split("/", 5) assert database == DEFAULT_DATABASE # Attach the fake GAPIC to a real client. credentials = mock.Mock(spec=google.auth.credentials.Credentials) client = Client(project=project, credentials=credentials) client._firestore_api_internal = firestore_api return client, client.document(doc_path)
def process_message(db: Client, message: Message): if not message.text: return chat_doc = db.collection("chats").document(str(message.chat_id)) chat_doc.set(message.chat.to_dict()) chat_doc.collection("messages").document(str(message.message_id)).set( message.to_dict() ) user = message.from_user try: db.collection("users").document(str(user.id)).create(user.to_dict()) except AlreadyExists: logging.info("%s already existed", user.first_name)
def auto_update_dispatcher_from_firebase_repliers(db: Client, dp: Dispatcher) -> Watch: # Create a callback on_snapshot function to capture changes def on_snapshot(col_snapshot, changes, read_time): existing_handlers: list = dp.handlers[0] existing_handlers.remove(UNKNOWN_COMMAND_ERROR_HANDLER) for change in changes: doc: dict = change.document.to_dict() id: str = change.document.id logging.info("%s replier %s - %r", change.type.name, id, doc) for h in existing_handlers: # delete the old handler regardless, because firebase sends "ADDED" events more than once if getattr(h, "name", "") == id: existing_handlers.remove(h) if change.type.name in ("ADDED", "MODIFIED"): # then just add it back again dp.add_handler( create_replier(name=id, **doc).to_message_handler()) elif change.type.name == "REMOVED": pass # make sure the "unknown command" handler is the last in the list existing_handlers.append(UNKNOWN_COMMAND_ERROR_HANDLER) query_watch = db.collection(u"repliers").on_snapshot(on_snapshot) return query_watch
def configure_db(): client = Client( project="firedantic-test", credentials=Mock(spec=google.auth.credentials.Credentials), ) prefix = str(uuid.uuid4()) + "-" configure(client, prefix)
def get_firebase_repliers(db: Client) -> list[BaseReplier]: for ref in db.collection("repliers").get(): ref_dict = ref.to_dict() try: yield create_replier(name=ref.id, **ref_dict) except Exception as exc: logging.exception("Could not load replier %s - %r", ref.id, ref_dict, exc_info=exc)
def parse_query(testcase): # 'query' testcase contains: # - 'coll_path': collection ref path. # - 'clauses': array of one or more 'Clause' elements # - 'query': the actual google.firestore_v1.StructuredQuery message # to be constructed. # - 'is_error' (as other testcases). # # 'Clause' elements are unions of: # - 'select': [field paths] # - 'where': (field_path, op, json_value) # - 'order_by': (field_path, direction) # - 'offset': int # - 'limit': int # - 'start_at': 'Cursor' # - 'start_after': 'Cursor' # - 'end_at': 'Cursor' # - 'end_before': 'Cursor' # # 'Cursor' contains either: # - 'doc_snapshot': 'DocSnapshot' # - 'json_values': [string] # # 'DocSnapshot' contains: # 'path': str # 'json_data': str from google.auth.credentials import Credentials from google.cloud.firestore_v1 import Client from google.cloud.firestore_v1 import Query _directions = {"asc": Query.ASCENDING, "desc": Query.DESCENDING} credentials = mock.create_autospec(Credentials) client = Client("projectID", credentials) path = parse_path(testcase.coll_path) collection = client.collection(*path) query = collection for clause in testcase.clauses: if "select" in clause: field_paths = [ ".".join(field_path.field) for field_path in clause.select.fields ] query = query.select(field_paths) elif "where" in clause: path = ".".join(clause.where.path.field) value = convert_data(json.loads(clause.where.json_value)) query = query.where(path, clause.where.op, value) elif "order_by" in clause: path = ".".join(clause.order_by.path.field) direction = clause.order_by.direction direction = _directions.get(direction, direction) query = query.order_by(path, direction=direction) elif "offset" in clause: query = query.offset(clause.offset) elif "limit" in clause: query = query.limit(clause.limit) elif "start_at" in clause: cursor = parse_cursor(clause.start_at, client) query = query.start_at(cursor) elif "start_after" in clause: cursor = parse_cursor(clause.start_after, client) query = query.start_after(cursor) elif "end_at" in clause: cursor = parse_cursor(clause.end_at, client) query = query.end_at(cursor) elif "end_before" in clause: cursor = parse_cursor(clause.end_before, client) query = query.end_before(cursor) else: # pragma: NO COVER raise ValueError("Unknown query clause: {}".format(clause)) return query
def test_listen_testprotos(test_proto): # pragma: NO COVER # test_proto.listen has 'reponses' messages, # 'google.firestore_v1.ListenResponse' # and then an expected list of 'snapshots' (local 'Snapshot'), containing # 'docs' (list of 'google.firestore_v1.Document'), # 'changes' (list lof local 'DocChange', and 'read_time' timestamp. from google.cloud.firestore_v1 import Client from google.cloud.firestore_v1 import DocumentReference from google.cloud.firestore_v1 import DocumentSnapshot from google.cloud.firestore_v1 import Watch import google.auth.credentials testcase = test_proto.listen testname = test_proto.description credentials = mock.Mock(spec=google.auth.credentials.Credentials) client = Client(project="project", credentials=credentials) modulename = "google.cloud.firestore_v1.watch" with mock.patch("%s.Watch.ResumableBidiRpc" % modulename, DummyRpc): with mock.patch("%s.Watch.BackgroundConsumer" % modulename, DummyBackgroundConsumer): with mock.patch( # conformance data sets WATCH_TARGET_ID to 1 "%s.WATCH_TARGET_ID" % modulename, 1): snapshots = [] def callback(keys, applied_changes, read_time): snapshots.append((keys, applied_changes, read_time)) collection = DummyCollection(client=client) query = DummyQuery(parent=collection) watch = Watch.for_query(query, callback, DocumentSnapshot, DocumentReference) # conformance data has db string as this db_str = "projects/projectID/databases/(default)" watch._firestore._database_string_internal = db_str wrapped_responses = [ firestore.ListenResponse.wrap(proto) for proto in testcase.responses ] if testcase.is_error: try: for proto in wrapped_responses: watch.on_snapshot(proto) except RuntimeError: # listen-target-add-wrong-id.textpro # listen-target-remove.textpro pass else: for proto in wrapped_responses: watch.on_snapshot(proto) assert len(snapshots) == len(testcase.snapshots) for i, (expected_snapshot, actual_snapshot) in enumerate( zip(testcase.snapshots, snapshots)): expected_changes = expected_snapshot.changes actual_changes = actual_snapshot[1] if len(expected_changes) != len(actual_changes): raise AssertionError( "change length mismatch in %s (snapshot #%s)" % (testname, i)) for y, (expected_change, actual_change) in enumerate( zip(expected_changes, actual_changes)): expected_change_kind = expected_change.kind actual_change_kind = actual_change.type.value if expected_change_kind != actual_change_kind: raise AssertionError( "change type mismatch in %s (snapshot #%s, change #%s')" % (testname, i, y))
def process_replier(db: Client, name: str, type: ReplierType, pattern: str, replies: list[str]): db.collection("repliers").document(name).create( dict(type=type.value, pattern=pattern, data=replies))
def parse_query(testcase): # 'query' testcase contains: # - 'coll_path': collection ref path. # - 'clauses': array of one or more 'Clause' elements # - 'query': the actual google.firestore_v1.StructuredQuery message # to be constructed. # - 'is_error' (as other testcases). # # 'Clause' elements are unions of: # - 'select': [field paths] # - 'where': (field_path, op, json_value) # - 'order_by': (field_path, direction) # - 'offset': int # - 'limit': int # - 'start_at': 'Cursor' # - 'start_after': 'Cursor' # - 'end_at': 'Cursor' # - 'end_before': 'Cursor' # # 'Cursor' contains either: # - 'doc_snapshot': 'DocSnapshot' # - 'json_values': [string] # # 'DocSnapshot' contains: # 'path': str # 'json_data': str from google.auth.credentials import Credentials from google.cloud.firestore_v1 import Client from google.cloud.firestore_v1 import Query _directions = {"asc": Query.ASCENDING, "desc": Query.DESCENDING} credentials = mock.create_autospec(Credentials) client = Client("projectID", credentials) path = parse_path(testcase.coll_path) collection = client.collection(*path) query = collection for clause in testcase.clauses: kind = clause.WhichOneof("clause") if kind == "select": field_paths = [ ".".join(field_path.field) for field_path in clause.select.fields ] query = query.select(field_paths) elif kind == "where": path = ".".join(clause.where.path.field) value = convert_data(json.loads(clause.where.json_value)) query = query.where(path, clause.where.op, value) elif kind == "order_by": path = ".".join(clause.order_by.path.field) direction = clause.order_by.direction direction = _directions.get(direction, direction) query = query.order_by(path, direction=direction) elif kind == "offset": query = query.offset(clause.offset) elif kind == "limit": query = query.limit(clause.limit) elif kind == "start_at": cursor = parse_cursor(clause.start_at, client) query = query.start_at(cursor) elif kind == "start_after": cursor = parse_cursor(clause.start_after, client) query = query.start_after(cursor) elif kind == "end_at": cursor = parse_cursor(clause.end_at, client) query = query.end_at(cursor) elif kind == "end_before": cursor = parse_cursor(clause.end_before, client) query = query.end_before(cursor) else: # pragma: NO COVER raise ValueError("Unknown query clause: {}".format(kind)) return query
def create_client(): return Client()