8000 all but error codes · rinlevan/firebase-admin-python@ce39c0c · GitHub
[go: up one dir, main page]

Skip to content

Commit ce39c0c

Browse files
committed
all but error codes
1 parent 7bde4f2 commit ce39c0c

File tree

4 files changed

+32
-84
lines changed

4 files changed

+32
-84
lines changed

firebase_admin/dynamic_links.py

Lines changed: 29 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
_LINKS_ATTRIBUTE = '_dynamic_links'
2929
_LINKS_BASE_URL = 'https://firebasedynamiclinks.googleapis.com/v1/'
3030

31+
_UNKNOWN_ERROR = 'unknown-error'
32+
3133
PLATFORM_DESKTOP = 'desktop'
3234
PLATFORM_IOS = 'ios'
3335
PLATFORM_ANDROID = 'android'
@@ -50,41 +52,42 @@ def get_link_stats(short_link, stat_options, app=None):
5052
app: A Firebase ``App instance`` (optional). (If missing uses default app.)
5153
5254
Returns:
53-
LinkStats: An ``LinkStats`` object. (containing an array of ``EventStats``)
55+
LinkStats: A ``LinkStats`` object. (containing an array of ``EventStats``)
5456
5557
Raises:
5658
ValueError: If any of the arguments are invalid.
57-
url must start with the protocol "http"
58-
stat_options should have a field with duration_days > 0
59+
short_link must start with the "https" protocol.
60+
stat_options should have duration_days > 0.
5961
"""
6062
return _get_link_service(app).get_stats(short_link, stat_options)
6163

6264
def _get_link_service(app):
63-
"""Returns an _LinksService instance for an App.
65+
"""Returns an _DynamicLinksService instance for an App.
6466
65-
If the App already has a _LinksService associated with it, simply returns
66-
it. Otherwise creates a new _LinksService, and adds it to the App before
67+
If the App already has a _DynamicLinksService associated with it, simply returns
68+
it. Otherwise creates a new _DynamicLinksService, and adds it to the App before
6769
returning it.
6870
6971
Args:
7072
app: A Firebase App instance (or None to use the default App).
7173
7274
Returns:
73-
_LinksService: An `_LinksService` for the specified App instance.
75+
_DynamicLinksService: An `_DynamicLinksService` for the specified App instance.
7476
7577
Raises:
7678
ValueError: If the app argument is invalid.
7779
"""
78-
return _utils.get_app_service(app, _LINKS_ATTRIBUTE, _LinksService)
80+
return _utils.get_app_service(app, _LINKS_ATTRIBUTE, _DynamicLinksService)
7981

8082

8183
class LinkStats(object):
82-
"""The ``LinkStats`` object is returned by get_link_stats, it contains a list of ``EventStats``"""
84+
"""The ``LinkStats`` object is returned by get_link_stats, it contains a list of
85+
``EventStats``"""
8386
def __init__(self, event_stats):
8487
if not isinstance(event_stats, (list, tuple)):
8588
raise ValueError('Invalid data argument: {0}. Must be a list or tuple'
8689
.format(event_stats))
87-
if event_stats and not isinstance(event_stats[0], EventStats):
90+
if not all(isinstance(es, EventStats) for es in event_stats):
8891
raise ValueError('Invalid data argument: elements of event stats must be' +
8992
' "EventStats", found{}'.format(type(event_stats[0])))
9093
self._stats = event_stats
@@ -117,28 +120,22 @@ class EventStats(object):
117120

118121
def __init__(self, platform, event, count):
119122
"""Create new instance of EventStats(platform, event, count)"""
120-
if isinstance(platform, six.string_types) and platform in self._platforms.keys():
121-
raise ValueError(('Raw string "{}" detected. Use a dynamic_links.PLATFORM_* constant' +
122-
' or the make_from_strings() method.').format(platform))
123123
if not isinstance(platform, six.string_types) or platform not in self._platforms.values():
124-
raise ValueError('platform {}, not recognized'.format(platform))
124+
raise ValueError('Invalid Platform value "{}".'.format(platform))
125125
self._platform = platform
126126

127-
if isinstance(event, six.string_types) and event in self._event_types.keys():
128-
raise ValueError(('Raw string {} detected. Use one of the dynamic_links.EVENT_TYPES_' +
129-
' constants, or the make_from_strings() method.').format(event))
130127
if not isinstance(event, six.string_types) or event not in self._event_types.values():
131-
raise ValueError('event_type {}, not recognized'.format(event))
128+
raise ValueError('Invalid Event Type value "{}".'.format(event))
132129
self._event = event
133130

134131
if not isinstance(count, int) or isinstance(count, bool) or count < 0:
135132
raise ValueError('Count: {} must be a non negative int'.format(count))
136133
self._count = count
137134

138135
@classmethod
139-
def make_from_strings(cls, platform, event, count):
140-
"""make_from_strings creates an EventStat object given the appropriate constants. e.g:
141-
make_from_strings(platform=PLATFORM_DESKTOP, event=EVENT_TYPE_REDIRECT, count=4)"""
136+
def _make_from_strings(cls, platform, event, count):
137+
"""_make_from_strings creates an EventStat object given the appropriate constants. e.g:
138+
_make_from_strings(platform=PLATFORM_DESKTOP, event=EVENT_TYPE_REDIRECT, count=4)"""
142139
return EventStats(cls._platforms[platform],
143140
cls._event_types[event],
144141
int(count))
@@ -158,22 +155,19 @@ def count(self):
158155

159156
class StatOptions(object):
160157
def __init__(self, duration_days):
161-
self.duration_days = duration_days
162-
163-
@property
164-
def duration_days(self):
165-
return self._duration_days
166-
167-
@duration_days.setter
168-
def duration_days(self, duration_days):
169158
if (isinstance(duration_days, bool)
170159
or not isinstance(duration_days, int)
171160
or duration_days < 1):
172161
raise ValueError('duration_days must be positive integer (got {})'
173162
.format(duration_days))
174163
self._duration_days = duration_days
175164

176-
class _LinksService(object):
165+
@property
166+
def duration_days(self):
167+
return self._duration_days
168+
169+
170+
class _DynamicLinksService(object):
177171
"""Provides methods for the Firebase dynamic links interaction"""
178172

179173
INTERNAL_ERROR = 'internal-error'
@@ -188,9 +182,7 @@ def __init__(self, app):
188182
def _format_request_string(self, short_link, options):
189183
days = options.duration_days
190184
# Complaints about the named second argument needed to replace "/"
191-
#pylint: disable=redundant-keyword-arg
192-
url_quoted = urllib.parse.quote(short_link, safe='')
193-
#pylint: enable=redundant-keyword-arg
185+
url_quoted = urllib.parse.quote(short_link, safe='') #pylint: disable=redundant-keyword-arg
194186
return self._request_string.format(url_quoted, days)
195187

196188
def get_stats(self, short_link, stat_options):
@@ -203,13 +195,12 @@ def get_stats(self, short_link, stat_options):
203195

204196
request_string = self._format_request_string(short_link, stat_options)
205197
try:
206-
resp = self._client.body('get', request_string)
198+
resp = self._client.body('get', request_string, timeout=self._timeout)
207199
except requests.exceptions.RequestException as error:
208-
209200
self._handle_error(error)
210201
else:
211-
link_event_stats_dict = resp.get('linkEventStats', [])
212-
event_stats = [EventStats.make_from_strings(**es) for es in link_event_stats_dict]
202+
link_event_stats = resp.get('linkEventStats', [])
203+
event_stats = [EventStats._make_from_strings(**es) for es in link_event_stats]
213204
return LinkStats(event_stats)
214205

215206
def _handle_error(self, error):
@@ -225,7 +216,7 @@ def _handle_error(self, error):
225216
except ValueError:
226217
pass
227218
error_details = data.get('error', {})
228-
code = error_details.get('code', 'undefined error code')
219+
code = error_details.get('code', _UNKNOWN_ERROR)
229220
msg = error_details.get('message')
230221
if not msg:
231222
msg = 'Unexpected HTTP response with status: {0}; body: {1}'.format(

integration/test_dynamic_links.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,13 @@ class TestEndToEnd(object):
3333
"""Runs an end-to-end test, see comment string for setup."""
3434

3535
def test_get_stats(self):
36-
if not dynamic_links_e2e_url:
37-
return
3836
link_stats = dynamic_links.get_link_stats(
3937
dynamic_links_e2e_url,
4038
dynamic_links.StatOptions(duration_days=4000))
4139
assert isinstance(link_stats, dynamic_links.LinkStats)
4240
assert len(link_stats.event_stats) > 0
4341

4442
def test_get_stats_nonexistant_link(self):
45-
if not dynamic_links_e2e_url:
46-
return
4743
link_stats = dynamic_links.get_link_stats(
4844
dynamic_links_e2e_url + 'some_arbitary_unlikely_string_ZXCzxcASDasdQWEqwe',
4945
dynamic_links.StatOptions(duration_days=4000))

tests/get_link_stats_vals.py

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

tests/test_dynamic_links.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@
2323
from firebase_admin import credentials
2424

2525
from tests import testutils
26-
from tests import get_link_stats_vals
2726

2827
MOCK_SHORT_URL = 'https://fake1.app.goo.gl/uQWc'
2928
MOCK_GET_STATS_RESPONSE = testutils.resource('get_link_stats.json')
29+
COMPARE_GET_STATS_VALS = testutils.resource('get_link_stats_vals.json')
3030

3131
MOCK_CREDENTIAL = credentials.Certificate(
3232
testutils.resource_filename('service_account.json'))
@@ -86,9 +86,8 @@ def test_get_stats(self, dynamic_links_test):
8686
for event_stat in link_stats.event_stats:
8787
assert isinstance(event_stat, dynamic_links.EventStats)
8888

89-
compared_event_stats = get_link_stats_vals.comparison
90-
assert len(compared_event_stats) == len(link_stats.event_stats)
91-
for (direct, returned) in zip(compared_event_stats, link_stats.event_stats):
89+
assert len(COMPARE_GET_STATS_VALS) = 1C6A = len(link_stats.event_stats)
90+
for (direct, returned) in zip(COMPARE_GET_STATS_VALS, link_stats.event_stats):
9291
assert returned.platform == direct['platform']
9392
assert returned.event == direct['event']
9493
assert returned.count == direct['count']

0 commit comments

Comments
 (0)
0