Skip to content

Commit a66fbe1

Browse files
authored
Merge pull request #10 from invertase/params-list-manifest
fix: user params should now show on manifest params list
2 parents 48871d1 + 8148723 commit a66fbe1

File tree

6 files changed

+63
-47
lines changed

6 files changed

+63
-47
lines changed

example/functions/main.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
"""
22
Example Firebase Functions written in Python
33
"""
4-
from firebase_functions import db, options, https
4+
from firebase_functions import db, options, https, params
55
from firebase_admin import initialize_app
66

77
initialize_app()
88

99
options.set_global_options(
1010
region=options.SupportedRegion.EUROPE_WEST1,
1111
memory=options.MemoryOption.MB_128,
12+
min_instances=params.IntParam("MIN", default=3),
1213
)
1314

1415

src/firebase_functions/params.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ def _quote_if_string(literal: _T) -> _T:
4747
return literal if not isinstance(literal, str) else f'"{literal}"'
4848

4949

50+
_params: dict[str, Expression] = {}
51+
52+
5053
@_dataclasses.dataclass(frozen=True)
5154
class TernaryExpression(Expression[_T], _typing.Generic[_T]):
5255
test: Expression[bool]
@@ -210,6 +213,11 @@ def __post_init__(self):
210213
raise ValueError(
211214
"Parameter names must only use uppercase letters, numbers and "
212215
"underscores, e.g. 'UPPER_SNAKE_CASE'.")
216+
if self.name in _params:
217+
raise ValueError(
218+
f"Duplicate Parameter Error: The parameter '{self.name}' has already been declared."
219+
)
220+
_params[self.name] = self
213221

214222

215223
@_dataclasses.dataclass(frozen=True)
@@ -247,6 +255,11 @@ def __post_init__(self):
247255
raise ValueError(
248256
"Parameter names must only use uppercase letters, numbers and "
249257
"underscores, e.g. 'UPPER_SNAKE_CASE'.")
258+
if self.name in _params:
259+
raise ValueError(
260+
f"Duplicate Parameter Error: The parameter '{self.name}' has already been declared."
261+
)
262+
_params[self.name] = self
250263

251264
def value(self) -> str:
252265
"""Current value of this parameter."""

src/firebase_functions/private/manifest.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14-
15-
1614
"""Specs for the served functions.yaml of the user's functions"""
1715

1816
# We're ignoring pylint's warning about names since we want
@@ -130,10 +128,8 @@ class ManifestRequiredApi(_typing.TypedDict):
130128
class ManifestStack:
131129
endpoints: dict[str, ManifestEndpoint]
132130
specVersion: str = "v1alpha1"
133-
params: _typing.Optional[list[_params.Param |
134-
_params.SecretParam]] = _dataclasses.field(
135-
default_factory=list[_params.Param |
136-
_params.SecretParam])
131+
params: list[_typing.Any] | None = _dataclasses.field(
132+
default_factory=list[_typing.Any])
137133
requiredAPIs: list[ManifestRequiredApi] = _dataclasses.field(
138134
default_factory=list[ManifestRequiredApi])
139135

src/firebase_functions/private/serving.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14-
15-
1614
"""
1715
Module used to serve Firebase functions locally and remotely.
1816
"""
@@ -29,6 +27,7 @@
2927
from flask import Response
3028

3129
from firebase_functions.private import manifest as _manifest
30+
from firebase_functions import params as _params
3231
from firebase_functions.private import util as _util
3332

3433

@@ -72,8 +71,9 @@ def functions_as_yaml(functions: dict) -> str:
7271
endpoint = function.__firebase_endpoint__
7372
# v2 function name(s) can only contain lower case letters, numbers, hyphens
7473
endpoints[name.replace("_", "-").lower()] = endpoint
75-
76-
manifest_stack = _manifest.ManifestStack(endpoints=endpoints)
74+
manifest_stack = _manifest.ManifestStack(endpoints=endpoints,
75+
params=list(
76+
_params._params.values()))
7777
manifest_spec = _manifest.manifest_to_spec_dict(manifest_stack)
7878
manifest_spec_with_sentinels = to_spec(manifest_spec)
7979

tests/test_manifest.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -132,21 +132,22 @@ def test_endpoint_to_dict(self):
132132

133133
def test_endpoint_expressions(self):
134134
"""Check Expression values convert to CEL strings."""
135+
max_param = _params.IntParam("MAX")
135136
expressions_test = _manifest.ManifestEndpoint(
136137
availableMemoryMb=_params.TernaryExpression(
137-
_params.BoolParam("LARGE"), 1024, 256),
138-
minInstances=_params.StringParam("LARGE").equals("yes").then(6, 1),
139-
maxInstances=_params.IntParam("MAX").compare(">", 6).then(
140-
6, _params.IntParam("MAX")),
138+
_params.BoolParam("LARGE_BOOL"), 1024, 256),
139+
minInstances=_params.StringParam("LARGE_STR").equals("yes").then(
140+
6, 1),
141+
maxInstances=max_param.compare(">", 6).then(6, max_param),
141142
timeoutSeconds=_params.IntParam("WORLD"),
142143
concurrency=_params.IntParam("BAR"),
143144
vpc={"connector": _params.SecretParam("SECRET")})
144145
expressions_expected_dict = {
145146
"platform": "gcfv2",
146147
"region": [],
147148
"secretEnvironmentVariables": [],
148-
"availableMemoryMb": "{{ params.LARGE ? 1024 : 256 }}",
149-
"minInstances": "{{ params.LARGE == \"yes\" ? 6 : 1 }}",
149+
"availableMemoryMb": "{{ params.LARGE_BOOL ? 1024 : 256 }}",
150+
"minInstances": "{{ params.LARGE_STR == \"yes\" ? 6 : 1 }}",
150151
"maxInstances": "{{ params.MAX > 6 ? 6 : params.MAX }}",
151152
"timeoutSeconds": "{{ params.WORLD }}",
152153
"concurrency": "{{ params.BAR }}",

tests/test_params.py

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,21 @@ class TestBoolParams:
2323

2424
def test_bool_param_value_true_or_false(self):
2525
"""Testing if bool params correctly returns a true or false value."""
26+
bool_param = params.BoolParam("BOOL_VALUE_TEST1")
2627
for value_true, value_false in zip(["true", "t", "1", "y", "yes"],
2728
["false", "f", "0", "n", "no"]):
28-
environ["BOOL_VALUE_TEST"] = value_true
29-
assert (params.BoolParam("BOOL_VALUE_TEST").value() is
29+
environ["BOOL_VALUE_TEST1"] = value_true
30+
assert (bool_param.value() is
3031
True), "Failure, params returned False"
31-
environ["BOOL_VALUE_TEST"] = value_false
32-
assert (params.BoolParam("BOOL_VALUE_TEST").value() is
32+
environ["BOOL_VALUE_TEST1"] = value_false
33+
assert (bool_param.value() is
3334
False), "Failure, params returned True"
3435

3536
def test_bool_param_value_error(self):
3637
"""Testing if bool params throws a value error if invalid value."""
3738
with pytest.raises(ValueError):
38-
environ["BOOL_VALUE_TEST"] = "bad_value"
39-
params.BoolParam("BOOL_VALUE_TEST").value()
39+
environ["BOOL_VALUE_TEST2"] = "bad_value"
40+
params.BoolParam("BOOL_VALUE_TEST2").value()
4041

4142
def test_bool_param_empty_default(self):
4243
"""Testing if bool params defaults to False if no value and no default."""
@@ -45,17 +46,19 @@ def test_bool_param_empty_default(self):
4546

4647
def test_bool_param_default(self):
4748
"""Testing if bool params defaults to provided default value."""
48-
assert (params.BoolParam("BOOL_DEFAULT_TEST", default=False).value() is
49+
assert (params.BoolParam("BOOL_DEFAULT_TEST_FALSE",
50+
default=False).value() is
4951
False), "Failure, params returned True"
50-
assert (params.BoolParam("BOOL_DEFAULT_TEST", default=True).value() is
52+
assert (params.BoolParam("BOOL_DEFAULT_TEST_TRUE",
53+
default=True).value() is
5154
True), "Failure, params returned False"
5255

5356
def test_bool_param_equality(self):
5457
"""Test bool equality."""
55-
assert (params.BoolParam("BOOL_TEST",
58+
assert (params.BoolParam("BOOL_TEST1",
5659
default=False).equals(False).value() is
5760
True), "Failure, equality check returned False"
58-
assert (params.BoolParam("BOOL_TEST",
61+
assert (params.BoolParam("BOOL_TEST2",
5962
default=True).equals(False).value() is
6063
False), "Failure, equality check returned False"
6164

@@ -71,20 +74,21 @@ def test_float_param_value(self):
7174

7275
def test_float_param_empty_default(self):
7376
"""Testing if float params defaults to empty float if no value and no default."""
74-
assert params.FloatParam("FLOAT_DEFAULT_TEST").value() == float(), \
77+
assert params.FloatParam("FLOAT_DEFAULT_TEST1").value() == float(), \
7578
"Failure, params value is not float"
7679

7780
def test_float_param_default(self):
7881
"""Testing if float param defaults to provided default value."""
79-
assert params.FloatParam("FLOAT_DEFAULT_TEST", default=float(456.789)).value() == 456.789, \
82+
assert params.FloatParam("FLOAT_DEFAULT_TEST2",
83+
default=float(456.789)).value() == 456.789, \
8084
"Failure, params default value != 456.789"
8185

8286
def test_float_param_equality(self):
8387
"""Test float equality."""
84-
assert (params.FloatParam("FLOAT_TEST",
88+
assert (params.FloatParam("FLOAT_TEST1",
8589
default=123.456).equals(123.456).value() is
8690
True), "Failure, equality check returned False"
87-
assert (params.FloatParam("FLOAT_TEST",
91+
assert (params.FloatParam("FLOAT_TEST2",
8892
default=456.789).equals(123.456).value() is
8993
False), "Failure, equality check returned False"
9094

@@ -100,19 +104,19 @@ def test_int_param_value(self):
100104

101105
def test_int_param_empty_default(self):
102106
"""Testing if int param defaults to empty int if no value and no default."""
103-
assert params.IntParam("INT_DEFAULT_TEST").value() == int(
107+
assert params.IntParam("INT_DEFAULT_TEST1").value() == int(
104108
), "Failure, params value is not int"
105109

106110
def test_int_param_default(self):
107111
"""Testing if int param defaults to provided default value."""
108-
assert params.IntParam("INT_DEFAULT_TEST", default=456).value() == 456, \
112+
assert params.IntParam("INT_DEFAULT_TEST2", default=456).value() == 456, \
109113
"Failure, params default value != 456"
110114

111115
def test_int_param_equality(self):
112116
"""Test int equality."""
113-
assert (params.IntParam("INT_TEST", default=123).equals(123).value() is
117+
assert (params.IntParam("INT_TEST1", default=123).equals(123).value() is
114118
True), "Failure, equality check returned False"
115-
assert (params.IntParam("INT_TEST", default=456).equals(123).value() is
119+
assert (params.IntParam("INT_TEST2", default=456).equals(123).value() is
116120
False), "Failure, equality check returned False"
117121

118122

@@ -133,21 +137,22 @@ def test_param_name_upper_snake_case(self):
133137

134138
def test_string_param_empty_default(self):
135139
"""Testing if string param defaults to empty string if no value and no default."""
136-
assert params.StringParam("STRING_DEFAULT_TEST").value() == str(), \
140+
assert params.StringParam("STRING_DEFAULT_TEST1").value() == str(), \
137141
"Failure, params value is not a string"
138142

139143
def test_string_param_default(self):
140144
"""Testing if string param defaults to provided default value."""
141-
assert (params.StringParam("STRING_DEFAULT_TEST", default="string_override_default").value()
145+
assert (params.StringParam("STRING_DEFAULT_TEST2",
146+
default="string_override_default").value()
142147
== "string_override_default"), \
143148
'Failure, params default value != "string_override_default"'
144149

145150
def test_string_param_equality(self):
146151
"""Test string equality."""
147-
assert (params.StringParam("STRING_TEST",
152+
assert (params.StringParam("STRING_TEST1",
148153
default="123").equals("123").value() is
149154
True), "Failure, equality check returned False"
150-
assert (params.StringParam("STRING_TEST",
155+
assert (params.StringParam("STRING_TEST2",
151156
default="456").equals("123").value() is
152157
False), "Failure, equality check returned False"
153158

@@ -157,30 +162,30 @@ class TestListParams:
157162

158163
def test_list_param_value(self):
159164
"""Testing if list param correctly returns list values."""
160-
environ["LIST_VALUE_TEST"] = "item1,item2"
161-
assert params.ListParam("LIST_VALUE_TEST").value() == ["item1","item2"], \
165+
environ["LIST_VALUE_TEST1"] = "item1,item2"
166+
assert params.ListParam("LIST_VALUE_TEST1").value() == ["item1","item2"], \
162167
'Failure, params value != ["item1","item2"]'
163168

164169
def test_list_param_filter_empty_strings(self):
165170
"""Testing if list param correctly returns list values wth empty strings excluded."""
166-
environ["LIST_VALUE_TEST"] = ",,item1,item2,,,item3,"
167-
assert params.ListParam("LIST_VALUE_TEST").value() == ["item1","item2", "item3"], \
171+
environ["LIST_VALUE_TEST2"] = ",,item1,item2,,,item3,"
172+
assert params.ListParam("LIST_VALUE_TEST2").value() == ["item1","item2", "item3"], \
168173
'Failure, params value != ["item1","item2", "item3"]'
169174

170175
def test_list_param_empty_default(self):
171176
"""Testing if list param defaults to an empty list if no value and no default."""
172-
assert params.ListParam("LIST_DEFAULT_TEST").value() == [], \
177+
assert params.ListParam("LIST_DEFAULT_TEST1").value() == [], \
173178
"Failure, params value is not an empty list"
174179

175180
def test_list_param_default(self):
176181
"""Testing if list param defaults to the provided default value."""
177-
assert (params.ListParam("LIST_DEFAULT_TEST", default=["1", "2"]).value()
182+
assert (params.ListParam("LIST_DEFAULT_TEST2", default=["1", "2"]).value()
178183
== ["1", "2"]), \
179184
'Failure, params default value != ["1", "2"]'
180185

181186
def test_list_param_equality(self):
182187
"""Test list equality."""
183-
assert (params.ListParam("LIST_TEST", default=["123"]).equals(
188+
assert (params.ListParam("LIST_TEST1", default=["123"]).equals(
184189
["123"]).value() is True), "Failure, equality check returned False"
185-
assert (params.ListParam("LIST_TEST", default=["456"]).equals(
190+
assert (params.ListParam("LIST_TEST2", default=["456"]).equals(
186191
["123"]).value() is False), "Failure, equality check returned False"

0 commit comments

Comments
 (0)