Skip to content

Commit 4eb9153

Browse files
authored
Merge pull request #39 from invertase/update-sphinx-docs-setup
refactor: rework for better generated reference docs
2 parents 6ecf5c3 + 51ceb3b commit 4eb9153

File tree

10 files changed

+209
-100
lines changed

10 files changed

+209
-100
lines changed

.github/workflows/ci.yaml

+30-4
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ jobs:
1515
python: ["3.10"]
1616

1717
steps:
18-
- uses: actions/checkout@v1
18+
- uses: actions/checkout@v3
1919
- name: Set up Python ${{ matrix.python }}
20-
uses: actions/setup-python@v1
20+
uses: actions/setup-python@v4
2121
with:
2222
python-version: ${{ matrix.python }}
2323
- name: Install dependencies
@@ -38,9 +38,9 @@ jobs:
3838
lint:
3939
runs-on: ubuntu-latest
4040
steps:
41-
- uses: actions/checkout@v1
41+
- uses: actions/checkout@v3
4242
- name: Set up Python
43-
uses: actions/setup-python@v1
43+
uses: actions/setup-python@v4
4444
with:
4545
python-version: "3.10"
4646
- name: Install dependencies
@@ -58,3 +58,29 @@ jobs:
5858
run: |
5959
source venv/bin/activate
6060
python3.10 -m mypy .
61+
62+
docs:
63+
runs-on: ubuntu-latest
64+
steps:
65+
- uses: actions/checkout@v3
66+
- name: Set up Python
67+
uses: actions/setup-python@v4
68+
with:
69+
python-version: "3.10"
70+
- name: Install dependencies
71+
run: |
72+
python3.10 -m venv venv
73+
source venv/bin/activate
74+
pip3 install --upgrade pip
75+
python3.10 -m pip install -r requirements.txt
76+
python3.10 setup.py install
77+
- name: Generate Reference Docs
78+
run: |
79+
source venv/bin/activate
80+
mkdir ./docs/build
81+
./docs/generate.sh --out=./docs/build/ --pypath=src/
82+
- uses: actions/upload-artifact@v3
83+
name: Upload Docs Preview
84+
with:
85+
name: reference-docs
86+
path: ./docs/build/

docs/generate.sh

+37-36
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/bin/sh
1+
#!/bin/bash
22
# Copyright 2022 Google Inc.
33
#
44
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -37,40 +37,40 @@ THEMEPATH=$(dirname $0)/theme
3737
THEMEPATH=$(realpath "$THEMEPATH")
3838

3939
if [[ $(uname) == "Darwin" ]]; then
40-
TEMPARGS=$(/Users/$(id -un)/homebrew/opt/gnu-getopt/bin/getopt -o o:p:b:t: --long out:,pypath:,sphinx-build:,themepath: -- "$@")
40+
TEMPARGS=$($(brew --prefix)/opt/gnu-getopt/bin/getopt -o o:p:b:t: --long out:,pypath:,sphinx-build:,themepath: -- "$@")
4141
else
4242
TEMPARGS=$(getopt -o o:p:b:t: --long out:,pypath:,sphinx-build:,themepath: -- "$@")
4343
getopt = getopt
4444
fi
4545
eval set -- "$TEMPARGS"
4646

4747
while true; do
48-
case "$1" in
49-
-o|--out)
50-
OUTDIR=$(realpath "$2")
51-
shift 2
52-
;;
53-
-p|--pypath)
54-
PYTHONPATH=$(realpath "$2"):"$PYTHONPATH"
55-
shift 2
56-
;;
57-
-b|--sphinx-build)
58-
SPHINXBIN=$(realpath "$2")
59-
shift 2
60-
;;
61-
-t|--themepath)
62-
THEMEPATH=$(realpath "$2")
63-
shift 2
64-
;;
65-
--)
66-
shift
67-
break
68-
;;
69-
*)
70-
echo Error
71-
exit 1
72-
;;
73-
esac
48+
case "$1" in
49+
-o | --out)
50+
OUTDIR=$(realpath "$2")
51+
shift 2
52+
;;
53+
-p | --pypath)
54+
PYTHONPATH=$(realpath "$2"):"$PYTHONPATH"
55+
shift 2
56+
;;
57+
-b | --sphinx-build)
58+
SPHINXBIN=$(realpath "$2")
59+
shift 2
60+
;;
61+
-t | --themepath)
62+
THEMEPATH=$(realpath "$2")
63+
shift 2
64+
;;
65+
--)
66+
shift
67+
break
68+
;;
69+
*)
70+
echo Error
71+
exit 1
72+
;;
73+
esac
7474
done
7575

7676
TARGET="$1"
@@ -82,20 +82,21 @@ if [[ "$OUTDIR" == "" ]]; then
8282
fi
8383

8484
TITLE="Firebase Python SDK for Cloud Functions"
85-
PY_MODULES='firebase_functions firebase_functions.core firebase_functions.https firebase_functions.params firebase_functions.db'
85+
PY_MODULES='firebase_functions firebase_functions.core firebase_functions.https firebase_functions.params firebase_functions.db firebase_functions.options firebase_functions.pubsub firebase_functions.storage'
8686
DEVSITE_PATH='/docs/reference/functions-python'
8787

8888
#
8989
# Set up temporary project
9090
#
9191
PROJDIR=$(mktemp -d)
9292
echo Created project directory: "$PROJDIR"
93-
pushd "$PROJDIR" > /dev/null
93+
pushd "$PROJDIR" >/dev/null
9494
mkdir _build
9595

9696
cat >conf.py <<EOL
9797
import devsite_translator.html
9898
99+
exclude_patterns = ['venv/**']
99100
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon']
100101
source_suffix = '.rst'
101102
master_doc = 'index'
@@ -110,8 +111,8 @@ def setup(app):
110111
app.set_translator('html', devsite_translator.html.FiresiteHTMLTranslator)
111112
EOL
112113

113-
for m in ${PY_MODULES};
114-
do cat >"$m".rst <<EOL
114+
for m in ${PY_MODULES}; do
115+
cat >"$m".rst <<EOL
115116
${m} module
116117
===============================================================================
117118
@@ -133,7 +134,7 @@ ${TITLE}
133134
EOL
134135

135136
for m in ${PY_MODULES}; do
136-
echo " ${m}" >> index.rst
137+
echo " ${m}" >>index.rst
137138
done
138139

139140
#
@@ -170,8 +171,8 @@ toc:
170171
path: ${DEVSITE_PATH}/
171172
EOL
172173
for m in ${PY_MODULES}; do
173-
echo "- title: ${m}" >> "$TOC"
174-
echo " path: ${DEVSITE_PATH}/${m}" >> "$TOC"
174+
echo "- title: ${m}" >>"$TOC"
175+
echo " path: ${DEVSITE_PATH}/${m}" >>"$TOC"
175176
done
176177

177-
popd > /dev/null
178+
popd >/dev/null

requirements.txt

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ Flask>=2.2.2
22
PyYAML>=6.0
33
pytest>=7.1.2
44
setuptools>=63.4.2
5-
pylint>=2.15.3
5+
pylint>=2.16.1
66
pytest-cov>=3.0.0
7-
mypy>=0.971
7+
mypy>=1.0.0
8+
sphinx>=6.1.3
9+
sphinxcontrib-napoleon>=0.7

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
install_requires = [
2222
'flask>=2.1.2', 'functions-framework>=3.0.0', 'firebase-admin>=6.0.0',
23-
'pyyaml>=6.0', 'typing-extensions>=4.3.0', 'cloudevents==1.9.0',
23+
'pyyaml>=6.0', 'typing-extensions>=4.4.0', 'cloudevents==1.9.0',
2424
'flask-cors>=3.0.10', 'pyjwt[crypto]>=2.5.0'
2525
]
2626

src/firebase_functions/core.py

-17
Original file line numberDiff line numberDiff line change
@@ -65,20 +65,3 @@ class CloudEvent(_typing.Generic[T]):
6565
The resource, provided by source, that this event relates to
6666
"""
6767

68-
69-
@_dataclass.dataclass(frozen=True)
70-
class Change(_typing.Generic[T]):
71-
"""
72-
* The Functions interface for events that change state, such as
73-
* Realtime Database `on_value_written`.
74-
"""
75-
76-
before: T
77-
"""
78-
The state of data before the change.
79-
"""
80-
81-
after: T
82-
"""
83-
The state of data after the change.
84-
"""

src/firebase_functions/db.py

+55-14
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 for Cloud Functions that are triggered by the Firebase Realtime Database.
1816
"""
@@ -21,18 +19,36 @@
2119
import functools as _functools
2220
import typing as _typing
2321
import datetime as _dt
24-
import firebase_functions.options as _options
2522
import firebase_functions.private.util as _util
2623
import firebase_functions.core as _core
2724
import cloudevents.http as _ce
28-
from firebase_functions.core import Change # Exported for user ease of typing events
25+
26+
from firebase_functions.options import DatabaseOptions
2927

3028
_event_type_written = "google.firebase.database.ref.v1.written"
3129
_event_type_created = "google.firebase.database.ref.v1.created"
3230
_event_type_updated = "google.firebase.database.ref.v1.updated"
3331
_event_type_deleted = "google.firebase.database.ref.v1.deleted"
3432

3533

34+
@_dataclass.dataclass(frozen=True)
35+
class Change(_typing.Generic[_core.T]):
36+
"""
37+
* The Functions interface for events that change state, such as
38+
* Realtime Database `on_value_written`.
39+
"""
40+
41+
before: _core.T
42+
"""
43+
The state of data before the change.
44+
"""
45+
46+
after: _core.T
47+
"""
48+
The state of data after the change.
49+
"""
50+
51+
3652
@_dataclass.dataclass(frozen=True)
3753
class Event(_core.CloudEvent[_core.T]):
3854
"""
@@ -87,7 +103,7 @@ def _db_endpoint_handler(
87103
# Merge delta into data to generate an 'after' view of the data.
88104
if isinstance(before, dict) and isinstance(after, dict):
89105
after = _util.prune_nones({**before, **after})
90-
database_event_data = _core.Change(
106+
database_event_data = Change(
91107
before=before,
92108
after=after,
93109
)
@@ -111,7 +127,7 @@ def _db_endpoint_handler(
111127
func(database_event)
112128

113129

114-
@_util.copy_func_kwargs(_options.DatabaseOptions)
130+
@_util.copy_func_kwargs(DatabaseOptions)
115131
def on_value_written(**kwargs) -> _typing.Callable[[_C1], _C1]:
116132
"""
117133
Event handler which triggers when data is created, updated, or deleted in Realtime Database.
@@ -124,8 +140,14 @@ def on_value_written(**kwargs) -> _typing.Callable[[_C1], _C1]:
124140
def example(event: Event[Change[object]]) -> None:
125141
pass
126142
143+
:param \\*\\*kwargs: Database options.
144+
:type \\*\\*kwargs: as :exc:`firebase_functions.options.DatabaseOptions`
145+
:rtype: :exc:`typing.Callable`
146+
\\[ \\[ :exc:`firebase_functions.db.Event` \\[
147+
:exc:`firebase_functions.db.Change` \\] \\], `None` \\]
148+
A function that takes a Database Event and returns None.
127149
"""
128-
options = _options.DatabaseOptions(**kwargs)
150+
options = DatabaseOptions(**kwargs)
129151

130152
def on_value_written_inner_decorator(func: _C1):
131153

@@ -143,7 +165,7 @@ def on_value_written_wrapped(raw: _ce.CloudEvent):
143165
return on_value_written_inner_decorator
144166

145167

146-
@_util.copy_func_kwargs(_options.DatabaseOptions)
168+
@_util.copy_func_kwargs(DatabaseOptions)
147169
def on_value_updated(**kwargs) -> _typing.Callable[[_C1], _C1]:
148170
"""
149171
Event handler which triggers when data is updated in Realtime Database.
@@ -156,8 +178,14 @@ def on_value_updated(**kwargs) -> _typing.Callable[[_C1], _C1]:
156178
def example(event: Event[Change[object]]) -> None:
157179
pass
158180
181+
:param \\*\\*kwargs: Database options.
182+
:type \\*\\*kwargs: as :exc:`firebase_functions.options.DatabaseOptions`
183+
:rtype: :exc:`typing.Callable`
184+
\\[ \\[ :exc:`firebase_functions.db.Event` \\[
185+
:exc:`firebase_functions.db.Change` \\] \\], `None` \\]
186+
A function that takes a Database Event and returns None.
159187
"""
160-
options = _options.DatabaseOptions(**kwargs)
188+
options = DatabaseOptions(**kwargs)
161189

162190
def on_value_updated_inner_decorator(func: _C1):
163191

@@ -175,7 +203,7 @@ def on_value_updated_wrapped(raw: _ce.CloudEvent):
175203
return on_value_updated_inner_decorator
176204

177205

178-
@_util.copy_func_kwargs(_options.DatabaseOptions)
206+
@_util.copy_func_kwargs(DatabaseOptions)
179207
def on_value_created(**kwargs) -> _typing.Callable[[_C2], _C2]:
180208
"""
181209
Event handler which triggers when data is created in Realtime Database.
@@ -185,10 +213,17 @@ def on_value_created(**kwargs) -> _typing.Callable[[_C2], _C2]:
185213
.. code-block:: python
186214
187215
@on_value_created(reference="*")
188-
def example(event):
216+
def example(event: Event[object]):
189217
pass
218+
219+
:param \\*\\*kwargs: Database options.
220+
:type \\*\\*kwargs: as :exc:`firebase_functions.options.DatabaseOptions`
221+
:rtype: :exc:`typing.Callable`
222+
\\[ \\[ :exc:`firebase_functions.db.Event` \\[
223+
:exc:`object` \\] \\], `None` \\]
224+
A function that takes a Database Event and returns None.
190225
"""
191-
options = _options.DatabaseOptions(**kwargs)
226+
options = DatabaseOptions(**kwargs)
192227

193228
def on_value_created_inner_decorator(func: _C2):
194229

@@ -206,7 +241,7 @@ def on_value_created_wrapped(raw: _ce.CloudEvent):
206241
return on_value_created_inner_decorator
207242

208243

209-
@_util.copy_func_kwargs(_options.DatabaseOptions)
244+
@_util.copy_func_kwargs(DatabaseOptions)
210245
def on_value_deleted(**kwargs) -> _typing.Callable[[_C2], _C2]:
211246
"""
212247
Event handler which triggers when data is deleted in Realtime Database.
@@ -219,8 +254,14 @@ def on_value_deleted(**kwargs) -> _typing.Callable[[_C2], _C2]:
219254
def example(event: Event[object]) -> None:
220255
pass
221256
257+
:param \\*\\*kwargs: Database options.
258+
:type \\*\\*kwargs: as :exc:`firebase_functions.options.DatabaseOptions`
259+
:rtype: :exc:`typing.Callable`
260+
\\[ \\[ :exc:`firebase_functions.db.Event` \\[
261+
:exc:`object` \\] \\], `None` \\]
262+
A function that takes a Database Event and returns None.
222263
"""
223-
options = _options.DatabaseOptions(**kwargs)
264+
options = DatabaseOptions(**kwargs)
224265

225266
def on_value_deleted_inner_decorator(func: _C2):
226267

0 commit comments

Comments
 (0)