Skip to content

Commit 02b4e06

Browse files
authored
Merge pull request #139 from cs50/develop
Fixes teardown_appcontext, adds support for multiple DB connections when using Flask
2 parents ddeba08 + dfe1d93 commit 02b4e06

File tree

3 files changed

+24
-17
lines changed

3 files changed

+24
-17
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
## Installation
66

77
```
8-
pip install cs50
8+
pip3 install cs50
99
```
1010

1111
## Usage

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@
1616
package_dir={"": "src"},
1717
packages=["cs50"],
1818
url="https://github.com/cs50/python-cs50",
19-
version="6.0.0"
19+
version="6.0.1"
2020
)

src/cs50/sql.py

+22-15
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ def __init__(self, url, **kwargs):
5656
# Create engine, disabling SQLAlchemy's own autocommit mode, raising exception if back end's module not installed
5757
self._engine = sqlalchemy.create_engine(url, **kwargs).execution_options(autocommit=False)
5858

59+
# Get logger
5960
self._logger = logging.getLogger("cs50")
6061

6162
# Listener for connections
@@ -77,7 +78,6 @@ def connect(dbapi_connection, connection_record):
7778
# Register listener
7879
sqlalchemy.event.listen(self._engine, "connect", connect)
7980

80-
8181
# Test database
8282
disabled = self._logger.disabled
8383
self._logger.disabled = True
@@ -275,24 +275,24 @@ def execute(self, sql, *args, **kwargs):
275275
# Infer whether app is defined
276276
assert flask.current_app
277277

278-
# If new context
279-
if not hasattr(flask.g, "_connection"):
278+
# If no connections to any databases yet
279+
if not hasattr(flask.g, "_connections"):
280+
setattr(flask.g, "_connections", {})
281+
connections = getattr(flask.g, "_connections")
280282

281-
# Ready to connect
282-
flask.g._connection = None
283+
# If not yet connected to this database
284+
# https://flask.palletsprojects.com/en/1.1.x/appcontext/#storing-data
285+
if self not in connections:
283286

284-
# Disconnect later
285-
@flask.current_app.teardown_appcontext
286-
def shutdown_session(exception=None):
287-
if flask.g._connection:
288-
flask.g._connection.close()
287+
# Connect to database
288+
connections[self] = self._engine.connect()
289289

290-
# If no connection for context yet
291-
if not flask.g._connection:
292-
flask.g._connection = self._engine.connect()
290+
# Disconnect from database later
291+
if _teardown_appcontext not in flask.current_app.teardown_appcontext_funcs:
292+
flask.current_app.teardown_appcontext(_teardown_appcontext)
293293

294-
# Use context's connection
295-
connection = flask.g._connection
294+
# Use this connection
295+
connection = connections[self]
296296

297297
except (ModuleNotFoundError, AssertionError):
298298

@@ -533,3 +533,10 @@ def _parse_placeholder(token):
533533

534534
# Invalid
535535
raise RuntimeError("{}: invalid placeholder".format(token.value))
536+
537+
538+
def _teardown_appcontext(exception=None):
539+
"""Closes context's database connection, if any."""
540+
import flask
541+
for connection in flask.g.pop("_connections", {}).values():
542+
connection.close()

0 commit comments

Comments
 (0)