diff --git a/.github/actions/setup-sqlite-version/action.yml b/.github/actions/setup-sqlite-version/action.yml deleted file mode 100644 index fdbc71c..0000000 --- a/.github/actions/setup-sqlite-version/action.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: "Setup SQLite version" -description: "Build and activate a specific SQLite version from its amalgamation archive" -inputs: - version: - description: "The SQLite version to install" - required: true - cflags: - description: "CFLAGS to use when compiling SQLite" - required: false - default: "" - skip-activate: - description: "Set to true to skip modifying the library path" - required: false - default: "false" - fallback-urls: - description: "Whitespace-separated fallback download URLs to try after sqlite.org" - required: false - default: "" -outputs: - sqlite-location: - description: "Directory containing the compiled SQLite library" - value: ${{ steps.build.outputs.sqlite-location }} -runs: - using: "composite" - steps: - - shell: bash - run: mkdir -p "$RUNNER_TEMP/sqlite-versions/downloads" - - uses: actions/cache@v6 - with: - path: ${{ runner.temp }}/sqlite-versions/downloads - key: setup-sqlite-version-${{ inputs.version }}-amalgamation-v1 - - id: build - shell: bash - run: bash "$GITHUB_ACTION_PATH/setup-sqlite-version.sh" - env: - SQLITE_VERSION: ${{ inputs.version }} - SQLITE_CFLAGS: ${{ inputs.cflags }} - SQLITE_SKIP_ACTIVATE: ${{ inputs.skip-activate }} - SQLITE_EXTRA_FALLBACK_URLS: ${{ inputs.fallback-urls }} diff --git a/.github/actions/setup-sqlite-version/setup-sqlite-version.sh b/.github/actions/setup-sqlite-version/setup-sqlite-version.sh deleted file mode 100644 index 0df7290..0000000 --- a/.github/actions/setup-sqlite-version/setup-sqlite-version.sh +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -version_spec="${SQLITE_VERSION:?SQLITE_VERSION is required}" -cflags="${SQLITE_CFLAGS:-}" -skip_activate="${SQLITE_SKIP_ACTIVATE:-false}" -extra_fallback_urls="${SQLITE_EXTRA_FALLBACK_URLS:-}" - -case "$version_spec" in - 3.46 | 3.46.0) - sqlite_version="3.46.0" - sqlite_year="2024" - amalgamation_id="3460000" - builtin_fallback_urls="https://static.simonwillison.net/static/2026/sqlite-amalgamation-3460000.zip" - ;; - 3.23.1) - sqlite_version="3.23.1" - sqlite_year="2018" - amalgamation_id="3230100" - builtin_fallback_urls="https://static.simonwillison.net/static/2026/sqlite-amalgamation-3230100.zip" - ;; - *) - echo "::error::Unsupported SQLite version '$version_spec'. Add its release year and amalgamation id to $GITHUB_ACTION_PATH/setup-sqlite-version.sh." - exit 1 - ;; -esac - -case "$(uname -s)" in - Linux) - library_name="libsqlite3.so.0" - library_path_var="LD_LIBRARY_PATH" - ;; - Darwin) - library_name="libsqlite3.dylib" - library_path_var="DYLD_LIBRARY_PATH" - ;; - *) - echo "::error::Unsupported platform $(uname -s)" - exit 1 - ;; -esac - -runner_temp="${RUNNER_TEMP:-}" -if [ -z "$runner_temp" ]; then - runner_temp="$(mktemp -d)" -fi - -filename="sqlite-amalgamation-${amalgamation_id}" -official_url="https://www.sqlite.org/${sqlite_year}/${filename}.zip" -download_dir="${runner_temp}/sqlite-versions/downloads" -source_root="${runner_temp}/sqlite-versions/source" -source_dir="${source_root}/${filename}" -build_dir="${runner_temp}/sqlite-versions/build/${sqlite_version}" -archive_path="${download_dir}/${filename}.zip" - -mkdir -p "$download_dir" "$source_root" "$build_dir" - -download_archive() { - local url - local candidate_path="${archive_path}.tmp" - local urls=("$official_url") - - for url in $builtin_fallback_urls $extra_fallback_urls; do - urls+=("$url") - done - - rm -f "$candidate_path" - for url in "${urls[@]}"; do - echo "Downloading SQLite ${sqlite_version} amalgamation from ${url}" - if curl \ - --fail \ - --location \ - --show-error \ - --retry 5 \ - --retry-delay 2 \ - --retry-max-time 180 \ - --retry-all-errors \ - --connect-timeout 20 \ - --max-time 240 \ - --output "$candidate_path" \ - "$url"; then - mv "$candidate_path" "$archive_path" - return 0 - fi - - echo "::warning::Download failed from ${url}" - rm -f "$candidate_path" - done - - echo "::error::Could not download SQLite ${sqlite_version} amalgamation" - return 1 -} - -if [ ! -f "${source_dir}/sqlite3.c" ]; then - if [ ! -f "$archive_path" ]; then - download_archive - fi - - rm -rf "$source_dir" - unzip -q "$archive_path" -d "$source_root" -fi - -if [ ! -f "${source_dir}/sqlite3.c" ]; then - echo "::error::Expected ${source_dir}/sqlite3.c after extracting ${archive_path}" - exit 1 -fi - -read -r -a cflag_args <<< "$cflags" - -echo "Compiling SQLite ${sqlite_version} to ${build_dir}/${library_name}" -gcc \ - -fPIC \ - -shared \ - "${cflag_args[@]}" \ - "${source_dir}/sqlite3.c" \ - "-I${source_dir}" \ - -o "${build_dir}/${library_name}" - -if [ "$library_name" = "libsqlite3.so.0" ]; then - ln -sf "$library_name" "${build_dir}/libsqlite3.so" -fi - -if [ -n "${GITHUB_OUTPUT:-}" ]; then - echo "sqlite-location=${build_dir}" >> "$GITHUB_OUTPUT" -else - echo "sqlite-location=${build_dir}" -fi - -case "$(printf '%s' "$skip_activate" | tr '[:upper:]' '[:lower:]')" in - true | 1 | yes) - echo "Skipping ${library_path_var} activation" - ;; - *) - existing_value="${!library_path_var:-}" - if [ -n "${GITHUB_ENV:-}" ]; then - if [ -n "$existing_value" ]; then - echo "${library_path_var}=${build_dir}:${existing_value}" >> "$GITHUB_ENV" - else - echo "${library_path_var}=${build_dir}" >> "$GITHUB_ENV" - fi - fi - echo "Added ${build_dir} to ${library_path_var}" - ;; -esac diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 23b23bd..d5a0b69 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -9,19 +9,24 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"] + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] os: [ubuntu-latest, windows-latest, macos-latest] steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v6 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - cache: pip - cache-dependency-path: pyproject.toml + - uses: actions/cache@v3 + name: Configure pip caching + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }} + restore-keys: | + ${{ runner.os }}-pip- - name: Install dependencies run: | - pip install . --group dev + pip install -e '.[test,tui]' - name: Run tests run: | pytest @@ -29,20 +34,25 @@ jobs: runs-on: ubuntu-latest needs: [test] steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@v4 with: - python-version: '3.14' - cache: pip - cache-dependency-path: pyproject.toml + python-version: '3.11' + - uses: actions/cache@v3 + name: Configure pip caching + with: + path: ~/.cache/pip + key: ${{ runner.os }}-publish-pip-${{ hashFiles('**/setup.py') }} + restore-keys: | + ${{ runner.os }}-publish-pip- - name: Install dependencies run: | - pip install build twine + pip install setuptools wheel twine - name: Publish env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} run: | - python -m build + python setup.py sdist bdist_wheel twine upload dist/* diff --git a/.github/workflows/spellcheck.yml b/.github/workflows/spellcheck.yml index 2afa7b7..8a86cd2 100644 --- a/.github/workflows/spellcheck.yml +++ b/.github/workflows/spellcheck.yml @@ -6,16 +6,21 @@ jobs: spellcheck: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 with: - python-version: "3.12" - cache: pip - cache-dependency-path: pyproject.toml + python-version: 3.9 + - uses: actions/cache@v2 + name: Configure pip caching + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }} + restore-keys: | + ${{ runner.os }}-pip- - name: Install dependencies run: | - pip install . --group docs + pip install -e '.[docs]' - name: Check spelling run: | codespell docs/*.rst --ignore-words docs/codespell-ignore-words.txt diff --git a/.github/workflows/test-coverage.yml b/.github/workflows/test-coverage.yml index 7668f1b..0681f66 100644 --- a/.github/workflows/test-coverage.yml +++ b/.github/workflows/test-coverage.yml @@ -12,19 +12,24 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repo - uses: actions/checkout@v7 + uses: actions/checkout@v2 - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@v2 with: - python-version: "3.11" - cache: pip - cache-dependency-path: pyproject.toml + python-version: 3.9 + - uses: actions/cache@v2 + name: Configure pip caching + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }} + restore-keys: | + ${{ runner.os }}-pip- - name: Install SpatiaLite run: sudo apt-get install libsqlite3-mod-spatialite - name: Install Python dependencies run: | python -m pip install --upgrade pip - python -m pip install . --group dev + python -m pip install -e .[test] python -m pip install pytest-cov - name: Run tests run: |- diff --git a/.github/workflows/test-sqlite-support.yml b/.github/workflows/test-sqlite-support.yml deleted file mode 100644 index f195cba..0000000 --- a/.github/workflows/test-sqlite-support.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Test SQLite versions - -on: [push, pull_request] - -permissions: - contents: read - -jobs: - test: - runs-on: ${{ matrix.platform }} - continue-on-error: true - strategy: - matrix: - platform: [ubuntu-latest] - python-version: ["3.10"] - sqlite-version: [ - "3.46", - "3.23.1", # 2018-04-10, before UPSERT - ] - steps: - - uses: actions/checkout@v7 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v6 - with: - python-version: ${{ matrix.python-version }} - allow-prereleases: true - cache: pip - cache-dependency-path: pyproject.toml - - name: Set up SQLite ${{ matrix.sqlite-version }} - uses: ./.github/actions/setup-sqlite-version - with: - version: ${{ matrix.sqlite-version }} - cflags: "-DSQLITE_ENABLE_DESERIALIZE -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_JSON1" - - run: python3 -c "import sqlite3; print(sqlite3.sqlite_version)" - - name: Install dependencies - run: | - pip install . --group dev - pip freeze - - name: Run tests - run: | - python -m pytest diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 923de2e..ab30b2d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,21 +10,25 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: ["3.10", "3.11", "3.12", "3.13", "3.14", "3.15-dev"] + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] numpy: [0, 1] - os: [ubuntu-latest, macos-latest, windows-latest, macos-14] + os: [ubuntu-latest, macos-latest, windows-latest] steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v6 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - allow-prereleases: true - cache: pip - cache-dependency-path: pyproject.toml + - uses: actions/cache@v3 + name: Configure pip caching + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }} + restore-keys: | + ${{ runner.os }}-pip- - name: Install dependencies run: | - pip install . --group dev + pip install -e '.[test,mypy,flake8,tui]' - name: Optionally install numpy if: matrix.numpy == 1 run: pip install numpy @@ -38,20 +42,13 @@ jobs: - name: Run tests run: | pytest -v - - name: Run autocommit tests just on 3.14/Ubuntu - if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.14' - run: pytest --sqlite-autocommit - name: run mypy run: mypy sqlite_utils tests - - name: run flake8 + - name: run flake8 if Python 3.8 or higher + if: matrix.python-version >= 3.8 run: flake8 - - name: run ty - if: matrix.os != 'windows-latest' && matrix.python-version == '3.14' - run: | - pip install uv - uv run ty check sqlite_utils - name: Check formatting run: black . --check - name: Check if cog needs to be run run: | - cog --check --diff README.md docs/*.rst + cog --check README.md docs/*.rst diff --git a/.gitignore b/.gitignore index 5b5d2c6..7947f33 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ .venv -dist build *.db __pycache__/ @@ -15,10 +14,9 @@ venv .schema .vscode .hypothesis -.claude/ Pipfile Pipfile.lock -uv.lock +pyproject.toml tests/*.dylib tests/*.so tests/*.dll diff --git a/.gitpod.yml b/.gitpod.yml new file mode 100644 index 0000000..fe8ba1e --- /dev/null +++ b/.gitpod.yml @@ -0,0 +1,2 @@ +tasks: +- init: pip install '.[test]' \ No newline at end of file diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 08c2f81..aa15c7c 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -4,14 +4,13 @@ sphinx: configuration: docs/conf.py build: - os: ubuntu-24.04 + os: ubuntu-22.04 tools: - python: "3.13" - jobs: - install: - - pip install --upgrade pip - - pip install . --group docs + python: "3.11" -formats: -- pdf -- epub +python: + install: + - method: pip + path: . + extra_requirements: + - docs diff --git a/Justfile b/Justfile index be41523..66863f6 100644 --- a/Justfile +++ b/Justfile @@ -1,34 +1,29 @@ # Run tests and linters @default: test lint +# Setup project +@init: + pipenv run pip install -e '.[test,docs,mypy,flake8]' + # Run pytest with supplied options @test *options: - uv run pytest {{options}} + pipenv run pytest {{options}} -@run *options: - uv run -- {{options}} - -# Run linters: black, flake8, mypy, ty, cog +# Run linters: black, flake8, mypy, cog @lint: - just run black . --check - uv run flake8 - uv run mypy sqlite_utils tests - uv run ty check sqlite_utils - uv run cog --check README.md docs/*.rst - uv run --group docs codespell docs/*.rst --ignore-words docs/codespell-ignore-words.txt - uv run --group docs codespell sqlite_utils --ignore-words docs/codespell-ignore-words.txt + pipenv run black . --check + pipenv run flake8 + pipenv run mypy sqlite_utils tests + pipenv run cog --check README.md docs/*.rst # Rebuild docs with cog @cog: - uv run --group docs cog -r README.md docs/*.rst + pipenv run cog -r README.md docs/*.rst # Serve live docs on localhost:8000 @docs: cog - #!/usr/bin/env bash - cd docs - uv run --group docs make livehtml - + cd docs && pipenv run make livehtml # Apply Black @black: - uv run black . + pipenv run black . diff --git a/README.md b/README.md index c444c64..49a26ed 100644 --- a/README.md +++ b/README.md @@ -18,12 +18,8 @@ Python CLI utility and library for manipulating SQLite databases. - [Configure SQLite full-text search](https://sqlite-utils.datasette.io/en/stable/cli.html#configuring-full-text-search) against your database tables and run search queries against them, ordered by relevance - Run [transformations against your tables](https://sqlite-utils.datasette.io/en/stable/cli.html#transforming-tables) to make schema changes that SQLite `ALTER TABLE` does not directly support, such as changing the type of a column - [Extract columns](https://sqlite-utils.datasette.io/en/stable/cli.html#extracting-columns-into-a-separate-table) into separate tables to better normalize your existing data -- [Manage database migrations](https://sqlite-utils.datasette.io/en/stable/migrations.html) using Python migration files and the `sqlite-utils migrate` command -- [Install plugins](https://sqlite-utils.datasette.io/en/stable/plugins.html) to add custom SQL functions and additional features -Upgrading from sqlite-utils 3.x? See the [4.0 upgrade guide](https://sqlite-utils.datasette.io/en/stable/upgrading.html#upgrading-from-3-x-to-4-0). - -Read more on my blog, in this series of posts on [New features in sqlite-utils](https://simonwillison.net/series/sqlite-utils-features/) and other [entries tagged sqlite-utils](https://simonwillison.net/tags/sqlite-utils/). +Read more on my blog, in this series of posts on [New features in sqlite-utils](https://simonwillison.net/series/sqlite-utils-features/) and other [entries tagged sqliteutils](https://simonwillison.net/tags/sqliteutils/). ## Installation diff --git a/docs/_static/img/tui.png b/docs/_static/img/tui.png new file mode 100644 index 0000000..04cbeb1 Binary files /dev/null and b/docs/_static/img/tui.png differ diff --git a/docs/_templates/base.html b/docs/_templates/base.html index a253a46..43c2003 100644 --- a/docs/_templates/base.html +++ b/docs/_templates/base.html @@ -7,11 +7,6 @@ {% block scripts %} {{ super() }} -