Skip to content

Commit

Permalink
Fix #86: add wn.config.allow_multithreading
Browse files Browse the repository at this point in the history
When set to `True`, the `check_same_thread` parameter to
`sqlite3.connect()` is set to `False`
  • Loading branch information
goodmami committed Jan 26, 2021
1 parent 4a02de8 commit 97e24f4
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 2 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
### Added

* `wn.Lexicon.specifier()`

* `wn.config.allow_multithreading` ([#86])

### Removed

Expand Down Expand Up @@ -192,6 +192,7 @@ abandoned, but this is an entirely new codebase.
[#79]: https://github.com/goodmami/wn/issues/79
[#81]: https://github.com/goodmami/wn/issues/81
[#83]: https://github.com/goodmami/wn/issues/83
[#86]: https://github.com/goodmami/wn/issues/86
[#90]: https://github.com/goodmami/wn/issues/90
[#92]: https://github.com/goodmami/wn/issues/92
[#93]: https://github.com/goodmami/wn/issues/93
7 changes: 7 additions & 0 deletions docs/api/wn.rst
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,13 @@ directly. Configuration should occur through the single

.. autoattribute:: data_directory
.. autoattribute:: database_path
.. attribute:: allow_multithreading

If set to :python:`True`, the database connection may be shared
across threads. In this case, it is the user's responsibility to
ensure that multiple threads don't try to write to the database
at the same time. The default is :python:`False`.

.. autoattribute:: downloads_directory
.. automethod:: add_project
.. automethod:: add_project_version
Expand Down
32 changes: 32 additions & 0 deletions tests/db_test.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

import sqlite3
import threading

import pytest

Expand All @@ -11,3 +12,34 @@ def test_schema_compatibility():
conn = sqlite3.connect(str(wn.config.database_path))
schema_hash = wn._db.schema_hash(conn)
assert schema_hash in wn._db.COMPATIBLE_SCHEMA_HASHES


@pytest.mark.usefixtures('mini_db')
def test_db_multithreading():
"""
See https://github.com/goodmami/wn/issues/86
Thanks: @fushinari
"""

class WNThread:
w = None

def __init__(self):
w_thread = threading.Thread(target=self.set_w)
w_thread.start()
w_thread.join()
self.w.synsets()

def set_w(self):
if self.w is None:
self.w = wn.Wordnet()

# close the connections by resetting the pool
wn._db.pool = {}
with pytest.raises(sqlite3.ProgrammingError):
WNThread()
wn._db.pool = {}
wn.config.allow_multithreading = True
WNThread() # no error
wn.config.allow_multithreading = False
wn._db.pool = {}
1 change: 1 addition & 0 deletions wn/_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def __init__(self):
self._data_directory = DEFAULT_DATA_DIRECTORY
self._projects = {}
self._dbpath = self._data_directory / DATABASE_FILENAME
self.allow_multithreading = False

@property
def data_directory(self) -> Path:
Expand Down
6 changes: 5 additions & 1 deletion wn/_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,11 @@ def connect() -> sqlite3.Connection:
dbpath = wn.config.database_path
if dbpath not in pool:
initialized = dbpath.is_file()
conn = sqlite3.connect(str(dbpath), detect_types=sqlite3.PARSE_DECLTYPES)
conn = sqlite3.connect(
str(dbpath),
detect_types=sqlite3.PARSE_DECLTYPES,
check_same_thread=not wn.config.allow_multithreading,
)
# foreign key support needs to be enabled for each connection
conn.execute('PRAGMA foreign_keys = ON')
if DEBUG:
Expand Down

0 comments on commit 97e24f4

Please sign in to comment.