html_url,issue_url,id,node_id,user,created_at,updated_at,author_association,body,reactions,issue,performed_via_github_app
https://github.com/simonw/datasette/issues/1744#issuecomment-1129251699,https://api.github.com/repos/simonw/datasette/issues/1744,1129251699,IC_kwDOBm6k_c5DTwNz,9599,2022-05-17T19:44:47Z,2022-05-17T19:46:38Z,OWNER,Updated docs: https://docs.datasette.io/en/latest/getting_started.html#using-datasette-on-your-own-computer and https://docs.datasette.io/en/latest/cli-reference.html#datasette-serve-help,"{""total_count"": 1, ""+1"": 1, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1239008850,
https://github.com/simonw/datasette/issues/1744#issuecomment-1129243427,https://api.github.com/repos/simonw/datasette/issues/1744,1129243427,IC_kwDOBm6k_c5DTuMj,9599,2022-05-17T19:35:02Z,2022-05-17T19:35:02Z,OWNER,"One thing to note is that the `datasette-copy-to-memory` plugin broke with a locked file, because it does this: https://github.com/simonw/datasette-copy-to-memory/blob/d541c18a78ae6f707a8f9b1e7fc4c020a9f68f2e/datasette_copy_to_memory/__init__.py#L27
```python
tmp.execute(""ATTACH DATABASE ? AS _copy_from"", [db.path])
```
That would need to use a URI filename too for it to work with locked files.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1239008850,
https://github.com/simonw/datasette/issues/1744#issuecomment-1129241873,https://api.github.com/repos/simonw/datasette/issues/1744,1129241873,IC_kwDOBm6k_c5DTt0R,9599,2022-05-17T19:33:16Z,2022-05-17T19:33:16Z,OWNER,"I'm going to skip adding a test for this - the test logic would have to be pretty convoluted to exercise it properly, and it's a pretty minor and low-risk feature in the scheme of things.","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1239008850,
https://github.com/simonw/datasette/issues/1744#issuecomment-1129241283,https://api.github.com/repos/simonw/datasette/issues/1744,1129241283,IC_kwDOBm6k_c5DTtrD,9599,2022-05-17T19:32:35Z,2022-05-17T19:32:35Z,OWNER,"I tried writing a test like this:
```python
@pytest.mark.parametrize(""locked"", (True, False))
def test_locked_sqlite_db(tmp_path_factory, locked):
dir = tmp_path_factory.mktemp(""test_locked_sqlite_db"")
test_db = str(dir / ""test.db"")
sqlite3.connect(test_db).execute(""create table t (id integer primary key)"")
if locked:
fp = open(test_db, ""w"")
fcntl.lockf(fp.fileno(), fcntl.LOCK_EX)
runner = CliRunner()
result = runner.invoke(
cli,
[
""serve"",
""--memory"",
""--get"",
""/test"",
],
catch_exceptions=False,
)
```
But it didn't work, because the test runs in the same process - so taking an exclusive lock on that file didn't cause an error when the test later tried to access it via Datasette!","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1239008850,
https://github.com/simonw/datasette/issues/1744#issuecomment-1129187486,https://api.github.com/repos/simonw/datasette/issues/1744,1129187486,IC_kwDOBm6k_c5DTgie,9599,2022-05-17T18:28:49Z,2022-05-17T18:28:49Z,OWNER,I think I do that with `fcntl.flock()`: https://docs.python.org/3/library/fcntl.html#fcntl.flock,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1239008850,
https://github.com/simonw/datasette/issues/1744#issuecomment-1129185356,https://api.github.com/repos/simonw/datasette/issues/1744,1129185356,IC_kwDOBm6k_c5DTgBM,9599,2022-05-17T18:26:26Z,2022-05-17T18:26:26Z,OWNER,Not sure how to test this - I'd need to open my own lock against a database file somehow.,"{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1239008850,
https://github.com/simonw/datasette/issues/1744#issuecomment-1129184908,https://api.github.com/repos/simonw/datasette/issues/1744,1129184908,IC_kwDOBm6k_c5DTf6M,9599,2022-05-17T18:25:57Z,2022-05-17T18:25:57Z,OWNER,"I knocked out a quick prototype of this and it worked!
datasette ~/Library/Application\ Support/Google/Chrome/Default/History --nolock
Here's the prototype diff:
```diff
diff --git a/datasette/app.py b/datasette/app.py
index b7b8437..f43700d 100644
--- a/datasette/app.py
+++ b/datasette/app.py
@@ -213,6 +213,7 @@ class Datasette:
config_dir=None,
pdb=False,
crossdb=False,
+ nolock=False,
):
assert config_dir is None or isinstance(
config_dir, Path
@@ -238,6 +239,7 @@ class Datasette:
self.databases = collections.OrderedDict()
self._refresh_schemas_lock = asyncio.Lock()
self.crossdb = crossdb
+ self.nolock = nolock
if memory or crossdb or not self.files:
self.add_database(Database(self, is_memory=True), name=""_memory"")
# memory_name is a random string so that each Datasette instance gets its own
diff --git a/datasette/cli.py b/datasette/cli.py
index 3c6e1b2..7e44665 100644
--- a/datasette/cli.py
+++ b/datasette/cli.py
@@ -452,6 +452,11 @@ def uninstall(packages, yes):
is_flag=True,
help=""Enable cross-database joins using the /_memory database"",
)
+@click.option(
+ ""--nolock"",
+ is_flag=True,
+ help=""Ignore locking and open locked files in read-only mode"",
+)
@click.option(
""--ssl-keyfile"",
help=""SSL key file"",
@@ -486,6 +491,7 @@ def serve(
open_browser,
create,
crossdb,
+ nolock,
ssl_keyfile,
ssl_certfile,
return_instance=False,
@@ -545,6 +551,7 @@ def serve(
version_note=version_note,
pdb=pdb,
crossdb=crossdb,
+ nolock=nolock,
)
# if files is a single directory, use that as config_dir=
diff --git a/datasette/database.py b/datasette/database.py
index 44d3266..fa55804 100644
--- a/datasette/database.py
+++ b/datasette/database.py
@@ -89,6 +89,8 @@ class Database:
# mode=ro or immutable=1?
if self.is_mutable:
qs = ""?mode=ro""
+ if self.ds.nolock:
+ qs += ""&nolock=1""
else:
qs = ""?immutable=1""
assert not (write and not self.is_mutable)
```","{""total_count"": 0, ""+1"": 0, ""-1"": 0, ""laugh"": 0, ""hooray"": 0, ""confused"": 0, ""heart"": 0, ""rocket"": 0, ""eyes"": 0}",1239008850,