diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 90e1a6e05..e9aba82e9 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -9,7 +9,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13"] os: [ubuntu-latest, windows-latest, macos-latest] steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/test-sqlite-support.yml b/.github/workflows/test-sqlite-support.yml index 256a2ce8c..fe9386529 100644 --- a/.github/workflows/test-sqlite-support.yml +++ b/.github/workflows/test-sqlite-support.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: platform: [ubuntu-latest] - python-version: ["3.9"] + python-version: ["3.10"] sqlite-version: [ "3.46", "3.23.1", # 2018-04-10, before UPSERT diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9561cdeeb..9c21c92a1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,13 +10,9 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.10", "3.11", "3.12", "3.13", "3.14-dev", "3.14t-dev"] numpy: [0, 1] os: [ubuntu-latest, macos-latest, windows-latest, macos-14] - # Skip 3.9 on macos-14 - it only has 3.10+ - exclude: - - python-version: "3.9" - os: macos-14 steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} @@ -60,4 +56,4 @@ jobs: run: black . --check - name: Check if cog needs to be run run: | - cog --check README.md docs/*.rst + cog --check --diff README.md docs/*.rst diff --git a/docs/cli-reference.rst b/docs/cli-reference.rst index e0d4fc543..18207c8f0 100644 --- a/docs/cli-reference.rst +++ b/docs/cli-reference.rst @@ -1479,7 +1479,7 @@ See :ref:`cli_spatialite`. paths. To load it from a specific path, use --load-extension. Options: - -t, --type [POINT|LINESTRING|POLYGON|MULTIPOINT|MULTILINESTRING|MULTIPOLYGON|GEOMETRYCOLLECTION|GEOMETRY] + -t, --type [point|linestring|polygon|multipoint|multilinestring|multipolygon|geometrycollection|geometry] Specify a geometry type for this column. [default: GEOMETRY] --srid INTEGER Spatial Reference ID. See diff --git a/setup.py b/setup.py index 892856532..24f68c0ae 100644 --- a/setup.py +++ b/setup.py @@ -63,7 +63,7 @@ def get_long_description(): "Issues": "https://github.com/simonw/sqlite-utils/issues", "CI": "https://github.com/simonw/sqlite-utils/actions", }, - python_requires=">=3.9", + python_requires=">=3.10", classifiers=[ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", @@ -71,7 +71,6 @@ def get_long_description(): "Intended Audience :: End Users/Desktop", "Topic :: Database", "License :: OSI Approved :: Apache Software License", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", diff --git a/sqlite_utils/cli.py b/sqlite_utils/cli.py index 5d3ba05ec..6b7ebd970 100644 --- a/sqlite_utils/cli.py +++ b/sqlite_utils/cli.py @@ -952,10 +952,14 @@ def insert_upsert_implementation( functions=None, strict=False, ): + convert = _value_or_none(convert) + delimiter = _value_or_none(delimiter) + quotechar = _value_or_none(quotechar) + encoding = _value_or_none(encoding) + bulk_sql = _value_or_none(bulk_sql) db = sqlite_utils.Database(path) _load_extensions(db, load_extension) - if functions: - _register_functions(db, functions) + _maybe_register_functions(db, functions) if (delimiter or quotechar or sniff or no_headers) and not tsv: csv = True if (nl + csv + tsv) >= 2: @@ -1790,8 +1794,7 @@ def query( _load_extensions(db, load_extension) db.register_fts4_bm25() - if functions: - _register_functions(db, functions) + _maybe_register_functions(db, functions) _execute_query( db, @@ -1917,6 +1920,9 @@ def memory( \b sqlite-utils memory animals.csv --schema """ + sql = _value_or_none(sql) + save = _value_or_none(save) + encoding = _value_or_none(encoding) db = sqlite_utils.Database(memory=True) # If --dump or --save or --analyze used but no paths detected, assume SQL query is a path: @@ -1990,8 +1996,7 @@ def memory( _load_extensions(db, load_extension) db.register_fts4_bm25() - if functions: - _register_functions(db, functions) + _maybe_register_functions(db, functions) if return_db: return db @@ -3066,14 +3071,14 @@ def wrapped_fn(value): "geometry_type", type=click.Choice( [ - "POINT", - "LINESTRING", - "POLYGON", - "MULTIPOINT", - "MULTILINESTRING", - "MULTIPOLYGON", - "GEOMETRYCOLLECTION", - "GEOMETRY", + "point", + "linestring", + "polygon", + "multipoint", + "multilinestring", + "multipolygon", + "geometrycollection", + "geometry", ], case_sensitive=False, ), @@ -3286,3 +3291,17 @@ def _register_functions(db, functions): for name, value in globals.items(): if callable(value) and not name.startswith("_"): db.register_function(value, name=name) + + +def _value_or_none(value): + if getattr(value, "__class__", None).__name__ == "Sentinel": + return None + return value + + +def _maybe_register_functions(db, functions): + functions = _value_or_none(functions) + if isinstance(functions, (bytes, bytearray)): + functions = functions.decode("utf-8") + if isinstance(functions, str) and functions.strip(): + _register_functions(db, functions)