Skip to content

Commit ceea2f0

Browse files
authored
Merge pull request #56 from invertase/firestore
feat: add support for Firestore 2nd gen triggers
2 parents 08586c8 + c60c860 commit ceea2f0

File tree

15 files changed

+598
-45
lines changed

15 files changed

+598
-45
lines changed

.github/workflows/ci.yaml

+4-8
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ jobs:
2525
python3.10 -m venv venv
2626
source venv/bin/activate
2727
pip3 install --upgrade pip
28-
python3.10 -m pip install -r requirements.txt
29-
python3.10 setup.py install
28+
python3.10 -m pip install -e ".[dev]"
3029
- name: Test with pytest & coverage
3130
run: |
3231
source venv/bin/activate
@@ -48,8 +47,7 @@ jobs:
4847
python3.10 -m venv venv
4948
source venv/bin/activate
5049
pip3 install --upgrade pip
51-
python3.10 -m pip install -r requirements.txt
52-
python3.10 setup.py install
50+
python3.10 -m pip install -e ".[dev]"
5351
- name: Lint with pylint
5452
run: |
5553
source venv/bin/activate
@@ -72,8 +70,7 @@ jobs:
7270
python3.10 -m venv venv
7371
source venv/bin/activate
7472
pip3 install --upgrade pip
75-
python3.10 -m pip install -r requirements.txt
76-
python3.10 setup.py install
73+
python3.10 -m pip install -e ".[dev]"
7774
- name: Generate Reference Docs
7875
run: |
7976
source venv/bin/activate
@@ -98,8 +95,7 @@ jobs:
9895
python3.10 -m venv venv
9996
source venv/bin/activate
10097
pip3 install --upgrade pip
101-
python3.10 -m pip install -r requirements.txt
102-
python3.10 setup.py install
98+
python3.10 -m pip install -e ".[dev]"
10399
- name: Check Formatting
104100
run: |
105101
source venv/bin/activate

requirements.txt

-11
This file was deleted.

samples/basic_firestore/.firebaserc

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"projects": {
3+
"default": "python-functions-testing"
4+
}
5+
}

samples/basic_firestore/.gitignore

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
firebase-debug.log*
8+
firebase-debug.*.log*
9+
10+
# Firebase cache
11+
.firebase/
12+
13+
# Firebase config
14+
15+
# Uncomment this if you'd like others to create their own Firebase project.
16+
# For a team working on the same Firebase project(s), it is recommended to leave
17+
# it commented so all members can deploy to the same project(s) in .firebaserc.
18+
# .firebaserc
19+
20+
# Runtime data
21+
pids
22+
*.pid
23+
*.seed
24+
*.pid.lock
25+
26+
# Directory for instrumented libs generated by jscoverage/JSCover
27+
lib-cov
28+
29+
# Coverage directory used by tools like istanbul
30+
coverage
31+
32+
# nyc test coverage
33+
.nyc_output
34+
35+
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
36+
.grunt
37+
38+
# Bower dependency directory (https://bower.io/)
39+
bower_components
40+
41+
# node-waf configuration
42+
.lock-wscript
43+
44+
# Compiled binary addons (http://nodejs.org/api/addons.html)
45+
build/Release
46+
47+
# Dependency directories
48+
node_modules/
49+
50+
# Optional npm cache directory
51+
.npm
52+
53+
# Optional eslint cache
54+
.eslintcache
55+
56+
# Optional REPL history
57+
.node_repl_history
58+
59+
# Output of 'npm pack'
60+
*.tgz
61+
62+
# Yarn Integrity file
63+
.yarn-integrity
64+
65+
# dotenv environment variables file
66+
.env

samples/basic_firestore/__init__.py

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Required to avoid a 'duplicate modules' mypy error
2+
# in monorepos that have multiple main.py files.
3+
# https://github.com/python/mypy/issues/4008

samples/basic_firestore/firebase.json

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"functions": [
3+
{
4+
"source": "functions",
5+
"codebase": "default",
6+
"ignore": [
7+
"venv"
8+
]
9+
}
10+
]
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# pyenv
2+
.python-version
3+
4+
# Installer logs
5+
pip-log.txt
6+
pip-delete-this-directory.txt
7+
8+
# Environments
9+
.env
10+
.venv
11+
venv/
12+
venv.bak/
13+
__pycache__
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""
2+
Example Firebase Functions for Firestore written in Python
3+
"""
4+
from firebase_functions import firestore_fn, options
5+
from firebase_admin import initialize_app
6+
7+
initialize_app()
8+
9+
options.set_global_options(region=options.SupportedRegion.EUROPE_WEST1)
10+
11+
12+
@firestore_fn.on_document_written(document="hello/{world}")
13+
def onfirestoredocumentwritten(
14+
event: firestore_fn.Event[firestore_fn.Change]) -> None:
15+
print("Hello from Firestore document write event:", event)
16+
17+
18+
@firestore_fn.on_document_created(document="hello/world")
19+
def onfirestoredocumentcreated(event: firestore_fn.Event) -> None:
20+
print("Hello from Firestore document create event:", event)
21+
22+
23+
@firestore_fn.on_document_deleted(document="hello/world")
24+
def onfirestoredocumentdeleted(event: firestore_fn.Event) -> None:
25+
print("Hello from Firestore document delete event:", event)
26+
27+
28+
@firestore_fn.on_document_updated(document="hello/world")
29+
def onfirestoredocumentupdated(
30+
event: firestore_fn.Event[firestore_fn.Change]) -> None:
31+
print("Hello from Firestore document updated event:", event)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Not published yet,
2+
# firebase-functions-python >= 0.0.1
3+
# so we use a relative path during development:
4+
./../../../
5+
# Or switch to git ref for deployment testing:
6+
# git+https://github.com/firebase/firebase-functions-python.git@main#egg=firebase-functions
7+
8+
firebase-admin >= 6.0.1

samples/basic_tasks/functions/requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@
66
# git+https://github.com/firebase/firebase-functions-python.git@main#egg=firebase-functions
77

88
firebase-admin >= 6.0.1
9+
google-cloud-tasks >= 2.13.1

setup.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,23 @@
1919
install_requires = [
2020
'flask>=2.1.2', 'functions-framework>=3.0.0', 'firebase-admin>=6.0.0',
2121
'pyyaml>=6.0', 'typing-extensions>=4.4.0', 'cloudevents==1.9.0',
22-
'flask-cors>=3.0.10', 'pyjwt[crypto]>=2.5.0'
22+
'flask-cors>=3.0.10', 'pyjwt[crypto]>=2.5.0', 'google-events>=0.5.0',
23+
'google-cloud-firestore>=2.11.0'
24+
]
25+
26+
dev_requires = [
27+
'pytest>=7.1.2', 'setuptools>=63.4.2', 'pylint>=2.16.1',
28+
'pytest-cov>=3.0.0', 'mypy>=1.0.0', 'sphinx>=6.1.3',
29+
'sphinxcontrib-napoleon>=0.7', 'yapf>=0.32.0', 'toml>=0.10.2',
30+
'google-cloud-tasks>=2.13.1'
2331
]
2432

2533
setup(
2634
name='firebase_functions',
2735
version='0.0.1',
2836
description='Firebase Functions Python SDK',
2937
install_requires=install_requires,
38+
extras_require={'dev': dev_requires},
3039
packages=find_packages(where='src'),
3140
package_dir={'': 'src'},
3241
python_requires='>=3.10',

src/firebase_functions/core.py

+18
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,21 @@ class CloudEvent(_typing.Generic[T]):
6262
"""
6363
The resource, provided by source, that this event relates to
6464
"""
65+
66+
67+
@_dataclass.dataclass(frozen=True)
68+
class Change(_typing.Generic[T]):
69+
"""
70+
* The Functions interface for events that change state, such as
71+
* Realtime Database `on_value_written`.
72+
"""
73+
74+
before: T
75+
"""
76+
The state of data before the change.
77+
"""
78+
79+
after: T
80+
"""
81+
The state of data after the change.
82+
"""

src/firebase_functions/db_fn.py

+8-25
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import cloudevents.http as _ce
2626

2727
from firebase_functions.options import DatabaseOptions
28+
from firebase_functions.core import Change, T
2829

2930
_event_type_written = "google.firebase.database.ref.v1.written"
3031
_event_type_created = "google.firebase.database.ref.v1.created"
@@ -33,25 +34,7 @@
3334

3435

3536
@_dataclass.dataclass(frozen=True)
36-
class Change(_typing.Generic[_core.T]):
37-
"""
38-
* The Functions interface for events that change state, such as
39-
* Realtime Database `on_value_written`.
40-
"""
41-
42-
before: _core.T
43-
"""
44-
The state of data before the change.
45-
"""
46-
47-
after: _core.T
48-
"""
49-
The state of data after the change.
50-
"""
51-
52-
53-
@_dataclass.dataclass(frozen=True)
54-
class Event(_core.CloudEvent[_core.T]):
37+
class Event(_core.CloudEvent[T]):
5538
"""
5639
A CloudEvent that contains a DataSnapshot or a Change<DataSnapshot>.
5740
"""
@@ -155,8 +138,8 @@ def example(event: Event[Change[object]]) -> None:
155138
:param \\*\\*kwargs: Database options.
156139
:type \\*\\*kwargs: as :exc:`firebase_functions.options.DatabaseOptions`
157140
:rtype: :exc:`typing.Callable`
158-
\\[ \\[ :exc:`firebase_functions.db.Event` \\[
159-
:exc:`firebase_functions.db.Change` \\] \\], `None` \\]
141+
\\[ \\[ :exc:`firebase_functions.db_fn.Event` \\[
142+
:exc:`firebase_functions.core.Change` \\] \\], `None` \\]
160143
A function that takes a Database Event and returns None.
161144
"""
162145
options = DatabaseOptions(**kwargs)
@@ -205,8 +188,8 @@ def example(event: Event[Change[object]]) -> None:
205188
:param \\*\\*kwargs: Database options.
206189
:type \\*\\*kwargs: as :exc:`firebase_functions.options.DatabaseOptions`
207190
:rtype: :exc:`typing.Callable`
208-
\\[ \\[ :exc:`firebase_functions.db.Event` \\[
209-
:exc:`firebase_functions.db.Change` \\] \\], `None` \\]
191+
\\[ \\[ :exc:`firebase_functions.db_fn.Event` \\[
192+
:exc:`firebase_functions.core.Change` \\] \\], `None` \\]
210193
A function that takes a Database Event and returns None.
211194
"""
212195
options = DatabaseOptions(**kwargs)
@@ -255,7 +238,7 @@ def example(event: Event[object]):
255238
:param \\*\\*kwargs: Database options.
256239
:type \\*\\*kwargs: as :exc:`firebase_functions.options.DatabaseOptions`
257240
:rtype: :exc:`typing.Callable`
258-
\\[ \\[ :exc:`firebase_functions.db.Event` \\[
241+
\\[ \\[ :exc:`firebase_functions.db_fn.Event` \\[
259242
:exc:`object` \\] \\], `None` \\]
260243
A function that takes a Database Event and returns None.
261244
"""
@@ -305,7 +288,7 @@ def example(event: Event[object]) -> None:
305288
:param \\*\\*kwargs: Database options.
306289
:type \\*\\*kwargs: as :exc:`firebase_functions.options.DatabaseOptions`
307290
:rtype: :exc:`typing.Callable`
308-
\\[ \\[ :exc:`firebase_functions.db.Event` \\[
291+
\\[ \\[ :exc:`firebase_functions.db_fn.Event` \\[
309292
:exc:`object` \\] \\], `None` \\]
310293
A function that takes a Database Event and returns None.
311294
"""

0 commit comments

Comments
 (0)