16
16
This module has required APIs for the clients to use Firebase Remote Config with python.
17
17
"""
18
18
19
+ import json
19
20
from typing import Dict , Optional
20
21
from firebase_admin import App , _http_client , _utils
21
22
import firebase_admin
22
23
23
24
_REMOTE_CONFIG_ATTRIBUTE = '_remoteconfig'
24
25
25
26
class ServerTemplateData :
26
- """Represents a Server Template Data class.
27
- """
28
- def __init__ (self , resp ):
29
-
30
- self ._parameters = resp .body .parameters
31
- self ._conditions = resp .body .conditions
32
- self ._version = resp .body .version
33
- self ._parameterGroups = resp .body .parameterGroups
34
- self ._etag = resp .headers .get ('etag' )
27
+ """Represents a Server Template Data class."""
28
+ def __init__ (self , headers , response_json ):
29
+ self ._parameters = response_json ['parameters' ]
30
+ self ._conditions = response_json ['conditions' ]
31
+ self ._version = response_json ['version' ]
32
+ self ._parameter_groups = response_json ['parameterGroups' ]
33
+ self ._etag = headers .get ('ETag' )
35
34
36
35
@property
37
36
def parameters (self ):
38
- # TODO: convert to Parameters
39
37
return self ._parameters
40
38
41
39
@property
@@ -49,79 +47,55 @@ def version(self):
49
47
@property
50
48
def conditions (self ):
51
49
return self ._conditions
52
-
53
- @property
54
- def conditions (self ):
55
- return self ._parameterGroups
56
-
57
- class Parameter :
58
- """ Representation of a remote config parameter."""
59
-
60
- def __init__ (self , default_value ):
61
- self ._default_value = default_value # ParameterValue
62
-
63
- @property
64
- def default_value (self ):
65
- return self ._default_value
66
-
67
-
68
- class ParameterValue :
69
- """ Base class to represent remote parameter values. A
70
- ParameterValue could be either an ExplicitParameterValue or an
71
- InAppDefaultValue. """
72
-
73
-
74
- class ExplicitParameterValue (ParameterValue ):
75
- def __init__ (self , value ):
76
- self ._value = value
77
50
78
51
@property
79
- def value (self ):
80
- return self ._value
81
-
82
- class InAppDefaultValue (ParameterValue ):
83
- def __init__ (self , use_in_app_default ):
84
- self ._use_in_app_default = use_in_app_default
85
-
86
- @property
87
- def use_in_app_default (self ):
88
- return self ._use_in_app_default
52
+ def parameter_groups (self ):
53
+ return self ._parameter_groups
89
54
90
55
91
56
class ServerTemplate :
92
- """Represents a Server Template with implementations for loading and evaluting the tempalte.
93
- """
57
+ """Represents a Server Template with implementations for loading and evaluting the tempalte."""
94
58
def __init__ (self , app : App = None , default_config : Optional [Dict [str , str ]] = None ):
95
- self . _rc_service = _utils . get_app_service ( app , _REMOTE_CONFIG_ATTRIBUTE , _RemoteConfigService )
59
+ """Initializes a ServerTemplate instance.
96
60
97
- # Field to represent the cached template. This gets set when the template is
61
+ Args:
62
+ app: App instance to be used. This is optional and the default app instance will
63
+ be used if not present.
64
+ default_config: The default config to be used in the evaluated config.
65
+ """
66
+ self ._rc_service = _utils .get_app_service (app ,
67
+ _REMOTE_CONFIG_ATTRIBUTE , _RemoteConfigService )
68
+
69
+ # This gets set when the template is
98
70
# fetched from RC servers via the load API, or via the set API.
99
71
self ._cache = None
100
72
if default_config is not None :
101
- for key in default_config :
102
- self ._stringified_default_config [key ] = default_config [key ]
73
+ self ._stringified_default_config = json .dumps (default_config )
103
74
else :
104
- self ._stringified_default_config [ key ] = None
75
+ self ._stringified_default_config = None
105
76
106
77
async def load (self ):
78
+ """Fetches the server template and caches the data."""
107
79
self ._cache = await self ._rc_service .getServerTemplate ()
108
80
109
- def evaluate (self , context : Optional [ Dict [ str , str | int ]] ):
110
- # Logic to process the cached template into a ServerConfig here
111
- # TODO: add Condition evaluator
112
- self ._evaluator = ConditionEvaluator (self ._cache .conditions , context )
81
+ def evaluate (self , context ):
82
+ # Logic to process the cached template into a ServerConfig here.
83
+ # TODO: Add Condition evaluator.
84
+ self ._evaluator = _ConditionEvaluator (self ._cache .conditions , context )
113
85
return ServerConfig (config_values = self ._evaluator .evaluate ())
114
86
115
87
def set (self , template ):
116
- if isinstance (template , str ):
117
- self ._cache = ServerTemplateData (template )
118
- elif isinstance (template , ServerTemplateData ):
88
+ """Updates the cache to store the given template is of type ServerTemplateData.
89
+
90
+ Args:
91
+ template: An object of type ServerTemplateData to be cached.
92
+ """
93
+ if isinstance (template , ServerTemplateData ):
119
94
self ._cache = template
120
95
121
96
122
97
class ServerConfig :
123
- """Represents a Remote Config Server Side Config.
124
- """
98
+ """Represents a Remote Config Server Side Config."""
125
99
def __init__ (self , config_values ):
126
100
self ._config_values = config_values # dictionary of param key to values
127
101
@@ -137,13 +111,18 @@ def get_int(self, key):
137
111
def get_value (self , key ):
138
112
return self ._config_values [key ]
139
113
140
- class _RemoteConfigService :
141
- """ Internal class that facilitates sending requests to the Firebase Remote
142
- Config backend API. """
143
114
115
+ class _RemoteConfigService :
116
+ """Internal class that facilitates sending requests to the Firebase Remote
117
+ Config backend API.
118
+ """
144
119
def __init__ (self , app ):
145
- # Initialize a JsonHttpClient with basic inputs. Referenced other
146
- # products' code in the Python SDK for what basic inputs to use.
120
+ """Initialize a JsonHttpClient with necessary inputs.
121
+
122
+ Args:
123
+ app: App instance to be used for fetching app specific details required
124
+ for initializing the http client.
125
+ """
147
126
remote_config_base_url = 'https://firebaseremoteconfig.googleapis.com'
148
127
self ._project_id = app .project_id
149
128
app_credential = app .credential .get_credential ()
@@ -157,24 +136,23 @@ def __init__(self, app):
157
136
158
137
159
138
def get_server_template (self ):
160
- # Requests for server template and converts the response to
161
- # ServerTemplateData
139
+ """ Requests for a server template and converts the response to an instance of
140
+ ServerTemplateData for storing the template parameters and conditions."""
162
141
url_prefix = self ._get_url_prefix ()
163
- response_json = self ._client .body ('get' ,
164
- url = url_prefix + '/namespaces/ \
165
- firebase-server/serverRemoteConfig' )
166
- return ServerTemplateData (response_json )
142
+ headers , response_json = self ._client .headers_and_body ('get' ,
143
+ url = url_prefix + '/namespaces/ \
144
+ firebase-server/serverRemoteConfig' )
145
+ return ServerTemplateData (headers , response_json )
167
146
168
147
def _get_url_prefix (self ):
169
148
# Returns project prefix for url, in the format of
170
149
# /v1/projects/${projectId}
171
150
return "/v1/projects/{0}" .format (self ._project_id )
172
-
173
151
174
- class _ConditionEvaluator :
175
- """ Internal class that facilitates sending requests to the Firebase Remote
176
- Config backend API. """
177
152
153
+ class _ConditionEvaluator :
154
+ """Internal class that facilitates sending requests to the Firebase Remote
155
+ Config backend API."""
178
156
def __init__ (self , context , conditions ):
179
157
self ._context = context
180
158
self ._conditions = conditions
@@ -185,13 +163,35 @@ def evaluate(self):
185
163
186
164
187
165
async def get_server_template (app : App = None , default_config : Optional [Dict [str , str ]] = None ):
188
- template = init_server_template (app , default_config )
166
+ """Initializes a new ServerTemplate instance and fetches the server template.
167
+
168
+ Args:
169
+ app: App instance to be used. This is optional and the default app instance will
170
+ be used if not present.
171
+ default_config: The default config to be used in the evaluated config.
172
+
173
+ Returns:
174
+ ServerTemplate: An object having the cached server template to be used for evaluation.
175
+ """
176
+ template = init_server_template (app = app , default_config = default_config )
189
177
await template .load ()
190
178
return template
191
179
192
- def init_server_template (app : App = None , default_config : Optional [Dict [str , str ]] = None ,
180
+ def init_server_template (app : App = None , default_config : Optional [Dict [str , str ]] = None ,
193
181
template_data : Optional [ServerTemplateData ] = None ):
194
- template = ServerTemplate (app , default_config = default_config )
182
+ """Initializes a new ServerTemplate instance.
183
+
184
+ Args:
185
+ app: App instance to be used. This is optional and the default app instance will
186
+ be used if not present.
187
+ default_config: The default config to be used in the evaluated config.
188
+ template_data: An optional template data to be set on initialization.
189
+
190
+ Returns:
191
+ ServerTemplate: A new ServerTemplate instance initialized with an optional
192
+ template and config.
193
+ """
194
+ template = ServerTemplate (app = app , default_config = default_config )
195
195
if template_data is not None :
196
196
template .set (template_data )
197
197
return template
0 commit comments