datasette-scan 0.1__tar.gz → 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datasette-scan
3
- Version: 0.1
3
+ Version: 0.1.1
4
4
  Summary: Datasette plugin for scanning for SQLite files
5
5
  Author: Simon Willison
6
6
  License-Expression: Apache-2.0
@@ -12,16 +12,19 @@ import time
12
12
  import sqlite_scanner
13
13
 
14
14
 
15
- def validate_databases(paths):
15
+ def validate_databases(paths, nolock=False):
16
16
  """Check each path is a readable SQLite database.
17
17
 
18
18
  Returns (valid, skipped) where skipped is a list of (path, reason) tuples.
19
19
  """
20
20
  valid = []
21
21
  skipped = []
22
+ qs = "?mode=ro"
23
+ if nolock:
24
+ qs += "&nolock=1"
22
25
  for path in paths:
23
26
  try:
24
- conn = sqlite3.connect(f"file:{path}?mode=ro", uri=True)
27
+ conn = sqlite3.connect(f"file:{path}{qs}", uri=True)
25
28
  try:
26
29
  conn.execute("SELECT * FROM sqlite_master")
27
30
  valid.append(path)
@@ -39,18 +42,14 @@ def scan_directories(directories):
39
42
  """
40
43
  binary = sqlite_scanner.get_binary_path()
41
44
  if not os.path.exists(binary):
42
- raise click.ClickException(
43
- f"sqlite-scanner binary not found at {binary}"
44
- )
45
+ raise click.ClickException(f"sqlite-scanner binary not found at {binary}")
45
46
  result = subprocess.run(
46
47
  [binary, "--jsonl"] + list(directories),
47
48
  capture_output=True,
48
49
  text=True,
49
50
  )
50
51
  if result.returncode != 0:
51
- raise click.ClickException(
52
- f"sqlite-scanner failed: {result.stderr.strip()}"
53
- )
52
+ raise click.ClickException(f"sqlite-scanner failed: {result.stderr.strip()}")
54
53
  paths = []
55
54
  for line in result.stdout.strip().splitlines():
56
55
  if line:
@@ -117,11 +116,9 @@ def register_commands(cli):
117
116
 
118
117
  # Validate scanned files, skip corrupted ones
119
118
  if scanned_files:
120
- valid, skipped = validate_databases(scanned_files)
119
+ valid, skipped = validate_databases(scanned_files, nolock=True)
121
120
  for path, reason in skipped:
122
- click.echo(
123
- f"Skipping {path}: {reason}", err=True
124
- )
121
+ click.echo(f"Skipping {path}: {reason}", err=True)
125
122
  db_files.extend(valid)
126
123
 
127
124
  # Always use nolock for safety with discovered files
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datasette-scan
3
- Version: 0.1
3
+ Version: 0.1.1
4
4
  Summary: Datasette plugin for scanning for SQLite files
5
5
  Author: Simon Willison
6
6
  License-Expression: Apache-2.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "datasette-scan"
3
- version = "0.1"
3
+ version = "0.1.1"
4
4
  description = "Datasette plugin for scanning for SQLite files"
5
5
  readme = "README.md"
6
6
  authors = [{name = "Simon Willison"}]
@@ -2,7 +2,11 @@ import click
2
2
  from click.testing import CliRunner
3
3
  from datasette.app import Datasette
4
4
  from datasette.cli import cli
5
- from datasette_scan import scan_directories, rescan_and_add_databases, validate_databases
5
+ from datasette_scan import (
6
+ scan_directories,
7
+ rescan_and_add_databases,
8
+ validate_databases,
9
+ )
6
10
  import json
7
11
  import os
8
12
  import pytest
@@ -50,9 +54,7 @@ def test_scan_has_serve_options():
50
54
  serve_option_names = {
51
55
  p.name for p in serve_cmd.params if isinstance(p, click.Option)
52
56
  }
53
- scan_option_names = {
54
- p.name for p in scan_cmd.params if isinstance(p, click.Option)
55
- }
57
+ scan_option_names = {p.name for p in scan_cmd.params if isinstance(p, click.Option)}
56
58
  # All serve options except nolock should be present on scan
57
59
  # nolock is always enabled for scan and not exposed as an option
58
60
  missing = serve_option_names - scan_option_names - {"nolock"}
@@ -62,9 +64,7 @@ def test_scan_has_serve_options():
62
64
  def test_scan_has_scan_interval_option():
63
65
  """scan should have the --scan-interval option that serve doesn't."""
64
66
  scan_cmd = cli.commands["scan"]
65
- scan_option_names = {
66
- p.name for p in scan_cmd.params if isinstance(p, click.Option)
67
- }
67
+ scan_option_names = {p.name for p in scan_cmd.params if isinstance(p, click.Option)}
68
68
  assert "scan_interval" in scan_option_names
69
69
 
70
70
 
@@ -80,9 +80,7 @@ def test_scan_directories_finds_sqlite_files(tmp_with_dbs):
80
80
  def test_scan_default_scans_current_directory(tmp_with_dbs):
81
81
  """With no args, scan should scan the current directory."""
82
82
  runner = CliRunner()
83
- result = runner.invoke(
84
- cli, ["scan", "--get", "/.json"], catch_exceptions=False
85
- )
83
+ result = runner.invoke(cli, ["scan", "--get", "/.json"], catch_exceptions=False)
86
84
  # We just need it to not error - with no SQLite in cwd it may serve
87
85
  # empty but should not crash
88
86
  assert result.exit_code == 0
File without changes
File without changes
File without changes