Skip to content

Commit b57af18

Browse files
authored
change(fcm): Remove deprecated FCM APIs (#890)
1 parent e4aff7e commit b57af18

File tree

8 files changed

+16
-962
lines changed

8 files changed

+16
-962
lines changed

firebase_admin/_gapic_utils.py

Lines changed: 0 additions & 122 deletions
This file was deleted.

firebase_admin/messaging.py

Lines changed: 0 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,16 @@
1818
from typing import Any, Callable, Dict, List, Optional, cast
1919
import concurrent.futures
2020
import json
21-
import warnings
2221
import asyncio
2322
import logging
2423
import requests
2524
import httpx
2625

27-
from googleapiclient import http
28-
from googleapiclient import _auth
29-
3026
import firebase_admin
3127
from firebase_admin import (
3228
_http_client,
3329
_messaging_encoder,
3430
_messaging_utils,
35-
_gapic_utils,
3631
_utils,
3732
exceptions,
3833
App
@@ -72,8 +67,6 @@
7267
'WebpushNotificationAction',
7368

7469
'send',
75-
'send_all',
76-
'send_multicast',
7770
'send_each',
7871
'send_each_async',
7972
'send_each_for_multicast',
@@ -246,64 +239,6 @@ def send_each_for_multicast(multicast_message, dry_run=False, app=None):
246239
) for token in multicast_message.tokens]
247240
return _get_messaging_service(app).send_each(messages, dry_run)
248241

249-
def send_all(messages, dry_run=False, app=None):
250-
"""Sends the given list of messages via Firebase Cloud Messaging as a single batch.
251-
252-
If the ``dry_run`` mode is enabled, the message will not be actually delivered to the
253-
recipients. Instead, FCM performs all the usual validations and emulates the send operation.
254-
255-
Args:
256-
messages: A list of ``messaging.Message`` instances.
257-
dry_run: A boolean indicating whether to run the operation in dry run mode (optional).
258-
app: An App instance (optional).
259-
260-
Returns:
261-
BatchResponse: A ``messaging.BatchResponse`` instance.
262-
263-
Raises:
264-
FirebaseError: If an error occurs while sending the message to the FCM service.
265-
ValueError: If the input arguments are invalid.
266-
267-
send_all() is deprecated. Use send_each() instead.
268-
"""
269-
warnings.warn('send_all() is deprecated. Use send_each() instead.', DeprecationWarning)
270-
return _get_messaging_service(app).send_all(messages, dry_run)
271-
272-
def send_multicast(multicast_message, dry_run=False, app=None):
273-
"""Sends the given mutlicast message to all tokens via Firebase Cloud Messaging (FCM).
274-
275-
If the ``dry_run`` mode is enabled, the message will not be actually delivered to the
276-
recipients. Instead, FCM performs all the usual validations and emulates the send operation.
277-
278-
Args:
279-
multicast_message: An instance of ``messaging.MulticastMessage``.
280-
dry_run: A boolean indicating whether to run the operation in dry run mode (optional).
281-
app: An App instance (optional).
282-
283-
Returns:
284-
BatchResponse: A ``messaging.BatchResponse`` instance.
285-
286-
Raises:
287-
FirebaseError: If an error occurs while sending the message to the FCM service.
288-
ValueError: If the input arguments are invalid.
289-
290-
send_multicast() is deprecated. Use send_each_for_multicast() instead.
291-
"""
292-
warnings.warn('send_multicast() is deprecated. Use send_each_for_multicast() instead.',
293-
DeprecationWarning)
294-
if not isinstance(multicast_message, MulticastMessage):
295-
raise ValueError('Message must be an instance of messaging.MulticastMessage class.')
296-
messages = [Message(
297-
data=multicast_message.data,
298-
notification=multicast_message.notification,
299-
android=multicast_message.android,
300-
webpush=multicast_message.webpush,
301-
apns=multicast_message.apns,
302-
fcm_options=multicast_message.fcm_options,
303-
token=token
304-
) for token in multicast_message.tokens]
305-
return _get_messaging_service(app).send_all(messages, dry_run)
306-
307242
def subscribe_to_topic(tokens, topic, app=None):
308243
"""Subscribes a list of registration tokens to an FCM topic.
309244
@@ -472,7 +407,6 @@ def __init__(self, app: App) -> None:
472407
self._client = _http_client.JsonHttpClient(credential=self._credential, timeout=timeout)
473408
self._async_client = _http_client.HttpxAsyncClient(
474409
credential=self._credential, timeout=timeout)
475-
self._build_transport = _auth.authorized_http
476410

477411
@classmethod
478412
def encode_message(cls, message):
@@ -555,45 +489,6 @@ async def send_data(data):
555489
message='Unknown error while making remote service calls: {0}'.format(error),
556490
cause=error)
557491

558-
559-
def send_all(self, messages, dry_run=False):
560-
"""Sends the given messages to FCM via the batch API."""
561-
if not isinstance(messages, list):
562-
raise ValueError('messages must be a list of messaging.Message instances.')
563-
if len(messages) > 500:
564-
raise ValueError('messages must not contain more than 500 elements.')
565-
566-
responses = []
567-
568-
def batch_callback(_, response, error):
569-
exception = None
570-
if error:
571-
exception = self._handle_batch_error(error)
572-
send_response = SendResponse(response, exception)
573-
responses.append(send_response)
574-
575-
batch = http.BatchHttpRequest(
576-
callback=batch_callback, batch_uri=_MessagingService.FCM_BATCH_URL)
577-
transport = self._build_transport(self._credential)
578-
for message in messages:
579-
body = json.dumps(self._message_data(message, dry_run))
580-
req = http.HttpRequest(
581-
http=transport,
582-
postproc=self._postproc,
583-
uri=self._fcm_url,
584-
method='POST',
585-
body=body,
586-
headers=self._fcm_headers
587-
)
588-
batch.add(req)
589-
590-
try:
591-
batch.execute()
592-
except Exception as error:
593-
raise self._handle_batch_error(error)
594-
else:
595-
return BatchResponse(responses)
596-
597492
def make_topic_management_request(self, tokens, topic, operation):
598493
"""Invokes the IID service for topic management functionality."""
599494
if isinstance(tokens, str):
@@ -670,11 +565,6 @@ def _handle_iid_error(self, error):
670565

671566
return _utils.handle_requests_error(error, msg)
672567

673-
def _handle_batch_error(self, error):
674-
"""Handles errors received from the googleapiclient while making batch requests."""
675-
return _gapic_utils.handle_platform_error_from_googleapiclient(
676-
error, _MessagingService._build_fcm_error_googleapiclient)
677-
678568
def close(self) -> None:
679569
asyncio.run(self._async_client.aclose())
680570

@@ -700,14 +590,6 @@ def _build_fcm_error_httpx(
700590
message, cause=error, http_response=error.response) if exc_type else None
701591
return exc_type(message, cause=error) if exc_type else None
702592

703-
704-
@classmethod
705-
def _build_fcm_error_googleapiclient(cls, error, message, error_dict, http_response):
706-
"""Parses an error response from the FCM API and creates a FCM-specific exception if
707-
appropriate."""
708-
exc_type = cls._build_fcm_error(error_dict)
709-
return exc_type(message, cause=error, http_response=http_response) if exc_type else None
710-
711593
@classmethod
712594
def _build_fcm_error(
713595
cls,

integration/test_messaging.py

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -149,71 +149,6 @@ def test_send_each_for_multicast():
149149
assert response.exception is not None
150150
assert response.message_id is None
151151

152-
@pytest.mark.skip(reason="Replaced with test_send_each")
153-
def test_send_all():
154-
messages = [
155-
messaging.Message(
156-
topic='foo-bar', notification=messaging.Notification('Title', 'Body')),
157-
messaging.Message(
158-
topic='foo-bar', notification=messaging.Notification('Title', 'Body')),
159-
messaging.Message(
160-
token='not-a-token', notification=messaging.Notification('Title', 'Body')),
161-
]
162-
163-
batch_response = messaging.send_all(messages, dry_run=True)
164-
165-
assert batch_response.success_count == 2
166-
assert batch_response.failure_count == 1
167-
assert len(batch_response.responses) == 3
168-
169-
response = batch_response.responses[0]
170-
assert response.success is True
171-
assert response.exception is None
172-
assert re.match('^projects/.*/messages/.*$', response.message_id)
173-
174-
response = batch_response.responses[1]
175-
assert response.success is True
176-
assert response.exception is None
177-
assert re.match('^projects/.*/messages/.*$', response.message_id)
178-
179-
response = batch_response.responses[2]
180-
assert response.success is False
181-
assert isinstance(response.exception, exceptions.InvalidArgumentError)
182-
assert response.message_id is None
183-
184-
@pytest.mark.skip(reason="Replaced with test_send_each_500")
185-
def test_send_all_500():
186-
messages = []
187-
for msg_number in range(500):
188-
topic = 'foo-bar-{0}'.format(msg_number % 10)
189-
messages.append(messaging.Message(topic=topic))
190-
191-
batch_response = messaging.send_all(messages, dry_run=True)
192-
193-
assert batch_response.success_count == 500
194-
assert batch_response.failure_count == 0
195-
assert len(batch_response.responses) == 500
196-
for response in batch_response.responses:
197-
assert response.success is True
198-
assert response.exception is None
199-
assert re.match('^projects/.*/messages/.*$', response.message_id)
200-
201-
@pytest.mark.skip(reason="Replaced with test_send_each_for_multicast")
202-
def test_send_multicast():
203-
multicast = messaging.MulticastMessage(
204-
notification=messaging.Notification('Title', 'Body'),
205-
tokens=['not-a-token', 'also-not-a-token'])
206-
207-
batch_response = messaging.send_multicast(multicast)
208-
209-
assert batch_response.success_count == 0
210-
assert batch_response.failure_count == 2
211-
assert len(batch_response.responses) == 2
212-
for response in batch_response.responses:
213-
assert response.success is False
214-
assert response.exception is not None
215-
assert response.message_id is None
216-
217152
def test_subscribe():
218153
resp = messaging.subscribe_to_topic(_REGISTRATION_TOKEN, 'mock-topic')
219154
assert resp.success_count + resp.failure_count == 1

requirements.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ respx == 0.22.0
99

1010
cachecontrol >= 0.12.14
1111
google-api-core[grpc] >= 1.22.1, < 3.0.0dev; platform.python_implementation != 'PyPy'
12-
google-api-python-client >= 1.7.8
1312
google-cloud-firestore >= 2.19.0; platform.python_implementation != 'PyPy'
1413
google-cloud-storage >= 1.37.1
1514
pyjwt[crypto] >= 2.5.0

setup.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
install_requires = [
4040
'cachecontrol>=0.12.14',
4141
'google-api-core[grpc] >= 1.22.1, < 3.0.0dev; platform.python_implementation != "PyPy"',
42-
'google-api-python-client >= 1.7.8',
4342
'google-cloud-firestore>=2.19.0; platform.python_implementation != "PyPy"',
4443
'google-cloud-storage>=1.37.1',
4544
'pyjwt[crypto] >= 2.5.0',

0 commit comments

Comments
 (0)