1616This module has required APIs for the clients to use Firebase Remote Config with python.
1717"""
1818
19+ import json
1920from typing import Dict , Optional
2021from firebase_admin import App , _http_client , _utils
2122import firebase_admin
2223
2324_REMOTE_CONFIG_ATTRIBUTE = '_remoteconfig'
2425
2526class 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' )
3534
3635 @property
3736 def parameters (self ):
38- # TODO: convert to Parameters
3937 return self ._parameters
4038
4139 @property
@@ -49,79 +47,55 @@ def version(self):
4947 @property
5048 def conditions (self ):
5149 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
7750
7851 @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
8954
9055
9156class 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."""
9458 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.
9660
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
9870 # fetched from RC servers via the load API, or via the set API.
9971 self ._cache = None
10072 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 )
10374 else :
104- self ._stringified_default_config [ key ] = None
75+ self ._stringified_default_config = None
10576
10677 async def load (self ):
78+ """Fetches the server template and caches the data."""
10779 self ._cache = await self ._rc_service .getServerTemplate ()
10880
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 )
11385 return ServerConfig (config_values = self ._evaluator .evaluate ())
11486
11587 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 ):
11994 self ._cache = template
12095
12196
12297class ServerConfig :
123- """Represents a Remote Config Server Side Config.
124- """
98+ """Represents a Remote Config Server Side Config."""
12599 def __init__ (self , config_values ):
126100 self ._config_values = config_values # dictionary of param key to values
127101
@@ -137,13 +111,18 @@ def get_int(self, key):
137111 def get_value (self , key ):
138112 return self ._config_values [key ]
139113
140- class _RemoteConfigService :
141- """ Internal class that facilitates sending requests to the Firebase Remote
142- Config backend API. """
143114
115+ class _RemoteConfigService :
116+ """Internal class that facilitates sending requests to the Firebase Remote
117+ Config backend API.
118+ """
144119 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+ """
147126 remote_config_base_url = 'https://firebaseremoteconfig.googleapis.com'
148127 self ._project_id = app .project_id
149128 app_credential = app .credential .get_credential ()
@@ -157,24 +136,23 @@ def __init__(self, app):
157136
158137
159138 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."""
162141 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 )
167146
168147 def _get_url_prefix (self ):
169148 # Returns project prefix for url, in the format of
170149 # /v1/projects/${projectId}
171150 return "/v1/projects/{0}" .format (self ._project_id )
172-
173151
174- class _ConditionEvaluator :
175- """ Internal class that facilitates sending requests to the Firebase Remote
176- Config backend API. """
177152
153+ class _ConditionEvaluator :
154+ """Internal class that facilitates sending requests to the Firebase Remote
155+ Config backend API."""
178156 def __init__ (self , context , conditions ):
179157 self ._context = context
180158 self ._conditions = conditions
@@ -185,13 +163,35 @@ def evaluate(self):
185163
186164
187165async 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 )
189177 await template .load ()
190178 return template
191179
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 ,
193181 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 )
195195 if template_data is not None :
196196 template .set (template_data )
197197 return template
0 commit comments