Skip to content

Commit

Permalink
Merge pull request #719 from tkrabel/named-inmemory-db
Browse files Browse the repository at this point in the history
Use in-memory database with shared cache
  • Loading branch information
lieryan authored Nov 5, 2023
2 parents 4c3b48c + 340176a commit 78315b5
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

- #710, #561 Implement `except*` syntax (@lieryan)
- #711 allow building documentation without having rope module installed (@kloczek)
- #719 Allows the in-memory db to be shared across threads (@tkrabel)
- #720 create one sqlite3.Connection per thread using a thread local (@tkrabel)

# Release 1.10.0
Expand Down
25 changes: 21 additions & 4 deletions rope/contrib/autoimport/sqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import contextlib
import json
from hashlib import sha256
import secrets
import re
import sqlite3
import sys
Expand Down Expand Up @@ -153,14 +155,29 @@ def create_database_connection(
memory : bool
if true, don't persist to disk
"""

def calculate_project_hash(data: str) -> str:
return sha256(data.encode()).hexdigest()

if not memory and project is None:
raise Exception("if memory=False, project must be provided")
db_path: str
if memory or project is None or project.ropefolder is None:
db_path = ":memory:"
# Allows the in-memory db to be shared across threads
# See https://www.sqlite.org/inmemorydb.html
project_hash: str
if project is None:
project_hash = secrets.token_hex()
elif project.ropefolder is None:
project_hash = calculate_project_hash(project.address)
else:
project_hash = calculate_project_hash(project.ropefolder.real_path)
return sqlite3.connect(
f"file:rope-{project_hash}:?mode=memory&cache=shared", uri=True
)
else:
db_path = str(Path(project.ropefolder.real_path) / "autoimport.db")
return sqlite3.connect(db_path)
return sqlite3.connect(
str(Path(project.ropefolder.real_path) / "autoimport.db")
)

@property
def connection(self):
Expand Down
7 changes: 7 additions & 0 deletions ropetest/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ def project():
testutils.remove_project(project)


@pytest.fixture
def project2():
project = testutils.sample_project("another_project")
yield project
testutils.remove_project(project)


@pytest.fixture
def project_path(project):
yield pathlib.Path(project.address)
Expand Down
15 changes: 15 additions & 0 deletions ropetest/contrib/autoimport/autoimporttest.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import sqlite3
from concurrent.futures import ThreadPoolExecutor
from contextlib import closing, contextmanager
from textwrap import dedent
Expand Down Expand Up @@ -27,6 +28,20 @@ def database_list(connection):
return list(connection.execute("PRAGMA database_list"))


def test_in_memory_database_share_cache(project, project2):
ai_1 = AutoImport(project, memory=True)
ai_2 = AutoImport(project, memory=True)

ai_3 = AutoImport(project2, memory=True)

with ai_1.connection:
ai_1.connection.execute("CREATE TABLE shared(data)")
ai_1.connection.execute("INSERT INTO shared VALUES(28)")
assert ai_2.connection.execute("SELECT data FROM shared").fetchone() == (28,)
with pytest.raises(sqlite3.OperationalError, match="no such table: shared"):
ai_3.connection.execute("SELECT data FROM shared").fetchone()


def test_autoimport_connection_parameter_with_in_memory(
project: Project,
autoimport: AutoImport,
Expand Down

0 comments on commit 78315b5

Please sign in to comment.