apsw-sqlite3mc 3.53.3.1__tar.gz → 3.53.4.0__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.
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/PKG-INFO +2 -2
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/README.rst +1 -1
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/__init__.pyi +116 -6
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/tests/__main__.py +107 -34
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/tests/async_meta.py +13 -6
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw_sqlite3mc.egg-info/PKG-INFO +2 -2
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/checksums +2 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/sqlite3/sqlite3.c +1024 -92
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/apsw.c +20 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/apsw.docstrings +49 -4
- apsw_sqlite3mc-3.53.4.0/src/apswversion.h +1 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/blob.c +255 -37
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/connection.c +2 -2
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/fts.c +10 -1
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/stringconstants.c +16 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/unicode.c +1 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/vfs.c +5 -1
- apsw_sqlite3mc-3.53.3.1/src/apswversion.h +0 -1
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/LICENSE +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/MANIFEST.in +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/__main__.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/aio.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/bestpractice.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/ext.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/fts5.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/fts5aux.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/fts5query.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/fts_test_strings +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/mcall.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/py.typed +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/shell.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/speedtest.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/sqlite_extra.json +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/sqlite_extra.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/sqlite_extra_binaries/README.md +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/tests/aiotest.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/tests/carray.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/tests/extratest.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/tests/fork_checker.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/tests/ftstests.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/tests/jsonb.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/tests/mctests.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/tests/sessiontests.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/tests/shelltest.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/trace.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw/unicode.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw_sqlite3mc.egg-info/SOURCES.txt +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw_sqlite3mc.egg-info/dependency_links.txt +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw_sqlite3mc.egg-info/entry_points.txt +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/apsw_sqlite3mc.egg-info/top_level.txt +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/pyproject.toml +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/setup.apsw +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/setup.cfg +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/setup.py +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/_unicodedb.c +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/argparse.c +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/async.c +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/backup.c +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/carray.c +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/constants.c +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/cursor.c +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/exceptions.c +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/faultinject.c +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/faultinject.h +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/fileio_win32.c +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/jsonb.c +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/pyutil.c +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/session.c +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/sqlite_debug.h +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/statementcache.c +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/testextension.c +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/traceback.c +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/util.c +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/src/vtable.c +0 -0
- {apsw_sqlite3mc-3.53.3.1 → apsw_sqlite3mc-3.53.4.0}/tools/vend.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: apsw_sqlite3mc
|
|
3
|
-
Version: 3.53.
|
|
3
|
+
Version: 3.53.4.0
|
|
4
4
|
Summary: SQLite3 Multiple Ciphers combined with Another Python SQLite Wrapper
|
|
5
5
|
Home-page: https://github.com/utelle/apsw-sqlite3mc
|
|
6
6
|
Author: Ulrich Telle
|
|
@@ -90,7 +90,7 @@ Setting the key on a new database is the only change needed to your code.
|
|
|
90
90
|
|
|
91
91
|
>>> import apsw
|
|
92
92
|
>>> print(apsw.mc_version)
|
|
93
|
-
SQLite3 Multiple Ciphers 2.
|
|
93
|
+
SQLite3 Multiple Ciphers 2.4.0
|
|
94
94
|
>>> con = apsw.Connection("database.sqlite3")
|
|
95
95
|
>>> con.pragma("key", "my secret passphrase")
|
|
96
96
|
ok
|
|
@@ -59,7 +59,7 @@ Setting the key on a new database is the only change needed to your code.
|
|
|
59
59
|
|
|
60
60
|
>>> import apsw
|
|
61
61
|
>>> print(apsw.mc_version)
|
|
62
|
-
SQLite3 Multiple Ciphers 2.
|
|
62
|
+
SQLite3 Multiple Ciphers 2.4.0
|
|
63
63
|
>>> con = apsw.Connection("database.sqlite3")
|
|
64
64
|
>>> con.pragma("key", "my secret passphrase")
|
|
65
65
|
ok
|
|
@@ -856,8 +856,8 @@ class Backup:
|
|
|
856
856
|
@final
|
|
857
857
|
class Blob:
|
|
858
858
|
"""This object is created by :meth:`Connection.blob_open` and provides
|
|
859
|
-
access to a blob in the database. It behaves like a Python
|
|
860
|
-
It wraps a `sqlite3_blob
|
|
859
|
+
access to a blob in the database. It behaves like a Python
|
|
860
|
+
:class:`file <io.RawIOBase>` in binary mode. It wraps a `sqlite3_blob
|
|
861
861
|
<https://sqlite.org/c3ref/blob.html>`_.
|
|
862
862
|
|
|
863
863
|
.. note::
|
|
@@ -893,6 +893,9 @@ class Blob:
|
|
|
893
893
|
Calls: `sqlite3_blob_close <https://sqlite.org/c3ref/blob_close.html>`__"""
|
|
894
894
|
...
|
|
895
895
|
|
|
896
|
+
closed: bool
|
|
897
|
+
"""Indicates if the blob has been closed."""
|
|
898
|
+
|
|
896
899
|
def __enter__(self) -> Blob:
|
|
897
900
|
"""You can use a blob as a `context manager
|
|
898
901
|
<https://docs.python.org/3/reference/datamodel.html#with-statement-context-managers>`_
|
|
@@ -913,6 +916,20 @@ class Blob:
|
|
|
913
916
|
*with* block is raised after closing the blob."""
|
|
914
917
|
...
|
|
915
918
|
|
|
919
|
+
def fileno(self) -> int:
|
|
920
|
+
"""Always raises :exc:`OSError` because there is no
|
|
921
|
+
underlying file descriptor."""
|
|
922
|
+
...
|
|
923
|
+
|
|
924
|
+
def flush(self) -> None:
|
|
925
|
+
"""Does nothing. There is no intermediate buffer, and SQLite's overall
|
|
926
|
+
transaction/savepoint handling deals with database commits."""
|
|
927
|
+
...
|
|
928
|
+
|
|
929
|
+
def isatty(self) -> False:
|
|
930
|
+
"""Blobs are never interactive."""
|
|
931
|
+
...
|
|
932
|
+
|
|
916
933
|
def length(self) -> int:
|
|
917
934
|
"""Returns the size of the blob in bytes.
|
|
918
935
|
|
|
@@ -951,6 +968,24 @@ class Blob:
|
|
|
951
968
|
|
|
952
969
|
readinto = read_into ## OLD-NAME
|
|
953
970
|
|
|
971
|
+
def readable(self) -> True:
|
|
972
|
+
"""You can always read from a blob"""
|
|
973
|
+
...
|
|
974
|
+
|
|
975
|
+
def readall(self) -> bytes:
|
|
976
|
+
"""Read all data until the end of the blob"""
|
|
977
|
+
...
|
|
978
|
+
|
|
979
|
+
def readline(self, size: int = -1) -> bytes:
|
|
980
|
+
"""Always raises :exc:`io.UnsupportedOperation`.
|
|
981
|
+
You can wrap with :class:`io.BufferedReader`."""
|
|
982
|
+
...
|
|
983
|
+
|
|
984
|
+
def readlines(self, hint: int = -1) -> list[bytes]:
|
|
985
|
+
"""Always raises :exc:`io.UnsupportedOperation`.
|
|
986
|
+
You can wrap with :class:`io.BufferedReader`."""
|
|
987
|
+
...
|
|
988
|
+
|
|
954
989
|
def reopen(self, rowid: int) -> None:
|
|
955
990
|
"""Change this blob object to point to a different row. It can be
|
|
956
991
|
faster than closing an existing blob an opening a new one.
|
|
@@ -968,13 +1003,28 @@ class Blob:
|
|
|
968
1003
|
:raises ValueError: If the resulting offset is before the beginning (less than zero) or beyond the end of the blob."""
|
|
969
1004
|
...
|
|
970
1005
|
|
|
1006
|
+
def seekable(self) -> True:
|
|
1007
|
+
"""You can always seek in a blob"""
|
|
1008
|
+
...
|
|
1009
|
+
|
|
971
1010
|
def tell(self) -> int:
|
|
972
1011
|
"""Returns the current offset."""
|
|
973
1012
|
...
|
|
974
1013
|
|
|
975
|
-
def
|
|
1014
|
+
def truncate(self, size = None) -> None:
|
|
1015
|
+
"""Always raises :exc:`io.UnsupportedOperation`.
|
|
1016
|
+
You cannot change the size of a blob."""
|
|
1017
|
+
...
|
|
1018
|
+
|
|
1019
|
+
def writable(self) -> bool:
|
|
1020
|
+
"""Returns True if the blob was open for writing, else False."""
|
|
1021
|
+
...
|
|
1022
|
+
|
|
1023
|
+
def write(self, data: Buffer) -> int:
|
|
976
1024
|
"""Writes the data to the blob.
|
|
977
1025
|
|
|
1026
|
+
Returns the number of bytes written, which will be all of them.
|
|
1027
|
+
|
|
978
1028
|
:param data: Buffer to write
|
|
979
1029
|
|
|
980
1030
|
:raises TypeError: Wrong data type
|
|
@@ -987,6 +1037,11 @@ class Blob:
|
|
|
987
1037
|
Calls: `sqlite3_blob_write <https://sqlite.org/c3ref/blob_write.html>`__"""
|
|
988
1038
|
...
|
|
989
1039
|
|
|
1040
|
+
def writelines(self, lines) -> None:
|
|
1041
|
+
"""Always raises :exc:`io.UnsupportedOperation`.
|
|
1042
|
+
You can wrap with :class:`io.BufferedWriter`."""
|
|
1043
|
+
...
|
|
1044
|
+
|
|
990
1045
|
@final
|
|
991
1046
|
class ChangesetBuilder:
|
|
992
1047
|
"""This object wraps a `sqlite3_changegroup <https://sqlite.org/session/changegroup.html>`__
|
|
@@ -6057,8 +6112,8 @@ class AsyncBlob:
|
|
|
6057
6112
|
"""This represents a :class:`Blob` when in async mode.
|
|
6058
6113
|
|
|
6059
6114
|
This object is created by :meth:`Connection.blob_open` and provides
|
|
6060
|
-
access to a blob in the database. It behaves like a Python
|
|
6061
|
-
It wraps a `sqlite3_blob
|
|
6115
|
+
access to a blob in the database. It behaves like a Python
|
|
6116
|
+
:class:`file <io.RawIOBase>` in binary mode. It wraps a `sqlite3_blob
|
|
6062
6117
|
<https://sqlite.org/c3ref/blob.html>`_.
|
|
6063
6118
|
|
|
6064
6119
|
.. note::
|
|
@@ -6103,8 +6158,25 @@ class AsyncBlob:
|
|
|
6103
6158
|
Calls: `sqlite3_blob_close <https://sqlite.org/c3ref/blob_close.html>`__"""
|
|
6104
6159
|
...
|
|
6105
6160
|
|
|
6161
|
+
closed: bool
|
|
6162
|
+
"""Indicates if the blob has been closed."""
|
|
6106
6163
|
|
|
6107
6164
|
|
|
6165
|
+
|
|
6166
|
+
def fileno(self) -> int:
|
|
6167
|
+
"""Always raises :exc:`OSError` because there is no
|
|
6168
|
+
underlying file descriptor."""
|
|
6169
|
+
...
|
|
6170
|
+
|
|
6171
|
+
async def flush(self) -> None:
|
|
6172
|
+
"""Does nothing. There is no intermediate buffer, and SQLite's overall
|
|
6173
|
+
transaction/savepoint handling deals with database commits."""
|
|
6174
|
+
...
|
|
6175
|
+
|
|
6176
|
+
def isatty(self) -> False:
|
|
6177
|
+
"""Blobs are never interactive."""
|
|
6178
|
+
...
|
|
6179
|
+
|
|
6108
6180
|
def length(self) -> int:
|
|
6109
6181
|
"""Returns the size of the blob in bytes.
|
|
6110
6182
|
|
|
@@ -6141,6 +6213,24 @@ class AsyncBlob:
|
|
|
6141
6213
|
Calls: `sqlite3_blob_read <https://sqlite.org/c3ref/blob_read.html>`__"""
|
|
6142
6214
|
...
|
|
6143
6215
|
|
|
6216
|
+
def readable(self) -> True:
|
|
6217
|
+
"""You can always read from a blob"""
|
|
6218
|
+
...
|
|
6219
|
+
|
|
6220
|
+
async def readall(self) -> bytes:
|
|
6221
|
+
"""Read all data until the end of the blob"""
|
|
6222
|
+
...
|
|
6223
|
+
|
|
6224
|
+
async def readline(self, size: int = -1) -> bytes:
|
|
6225
|
+
"""Always raises :exc:`io.UnsupportedOperation`.
|
|
6226
|
+
You can wrap with :class:`io.BufferedReader`."""
|
|
6227
|
+
...
|
|
6228
|
+
|
|
6229
|
+
async def readlines(self, hint: int = -1) -> list[bytes]:
|
|
6230
|
+
"""Always raises :exc:`io.UnsupportedOperation`.
|
|
6231
|
+
You can wrap with :class:`io.BufferedReader`."""
|
|
6232
|
+
...
|
|
6233
|
+
|
|
6144
6234
|
async def reopen(self, rowid: int) -> None:
|
|
6145
6235
|
"""Change this blob object to point to a different row. It can be
|
|
6146
6236
|
faster than closing an existing blob an opening a new one.
|
|
@@ -6158,13 +6248,28 @@ class AsyncBlob:
|
|
|
6158
6248
|
:raises ValueError: If the resulting offset is before the beginning (less than zero) or beyond the end of the blob."""
|
|
6159
6249
|
...
|
|
6160
6250
|
|
|
6251
|
+
def seekable(self) -> True:
|
|
6252
|
+
"""You can always seek in a blob"""
|
|
6253
|
+
...
|
|
6254
|
+
|
|
6161
6255
|
def tell(self) -> int:
|
|
6162
6256
|
"""Returns the current offset."""
|
|
6163
6257
|
...
|
|
6164
6258
|
|
|
6165
|
-
async def
|
|
6259
|
+
async def truncate(self, size = None) -> None:
|
|
6260
|
+
"""Always raises :exc:`io.UnsupportedOperation`.
|
|
6261
|
+
You cannot change the size of a blob."""
|
|
6262
|
+
...
|
|
6263
|
+
|
|
6264
|
+
def writable(self) -> bool:
|
|
6265
|
+
"""Returns True if the blob was open for writing, else False."""
|
|
6266
|
+
...
|
|
6267
|
+
|
|
6268
|
+
async def write(self, data: Buffer) -> int:
|
|
6166
6269
|
"""Writes the data to the blob.
|
|
6167
6270
|
|
|
6271
|
+
Returns the number of bytes written, which will be all of them.
|
|
6272
|
+
|
|
6168
6273
|
:param data: Buffer to write
|
|
6169
6274
|
|
|
6170
6275
|
:raises TypeError: Wrong data type
|
|
@@ -6177,6 +6282,11 @@ class AsyncBlob:
|
|
|
6177
6282
|
Calls: `sqlite3_blob_write <https://sqlite.org/c3ref/blob_write.html>`__"""
|
|
6178
6283
|
...
|
|
6179
6284
|
|
|
6285
|
+
async def writelines(self, lines) -> None:
|
|
6286
|
+
"""Always raises :exc:`io.UnsupportedOperation`.
|
|
6287
|
+
You can wrap with :class:`io.BufferedWriter`."""
|
|
6288
|
+
...
|
|
6289
|
+
|
|
6180
6290
|
class AsyncConnection:
|
|
6181
6291
|
"""This represents a :class:`Connection` when in async mode.
|
|
6182
6292
|
|
|
@@ -379,24 +379,20 @@ class APSW(unittest.TestCase):
|
|
|
379
379
|
if name in apsw.vfs_names():
|
|
380
380
|
apsw.unregister_vfs(name)
|
|
381
381
|
|
|
382
|
-
def check_db_mutex(self):
|
|
382
|
+
def check_db_mutex(self, db):
|
|
383
383
|
# verify a db mutex is not being held by doing work in another
|
|
384
384
|
# thread
|
|
385
|
-
try:
|
|
386
|
-
self.db.readonly("main")
|
|
387
|
-
except apsw.ConnectionClosedError:
|
|
388
|
-
return
|
|
389
385
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
386
|
+
db.set_progress_handler(None)
|
|
387
|
+
db.exec_trace = None
|
|
388
|
+
db.row_trace = None
|
|
393
389
|
|
|
394
390
|
val = Exception("The database mutex is still held and should not be")
|
|
395
391
|
|
|
396
392
|
def thread():
|
|
397
393
|
nonlocal val
|
|
398
394
|
try:
|
|
399
|
-
val =
|
|
395
|
+
val = db.execute("select 3").get
|
|
400
396
|
except BaseException as exc:
|
|
401
397
|
val = exc
|
|
402
398
|
|
|
@@ -412,14 +408,10 @@ class APSW(unittest.TestCase):
|
|
|
412
408
|
|
|
413
409
|
def tearDown(self):
|
|
414
410
|
apsw.config(apsw.SQLITE_CONFIG_LOG, None)
|
|
415
|
-
if self.db is not None:
|
|
416
|
-
try:
|
|
417
|
-
self.check_db_mutex()
|
|
418
|
-
finally:
|
|
419
|
-
self.db.close(True)
|
|
420
|
-
del self.db
|
|
421
411
|
for c in apsw.connections():
|
|
422
|
-
|
|
412
|
+
self.check_db_mutex(c)
|
|
413
|
+
c.close(True)
|
|
414
|
+
del self.db
|
|
423
415
|
gc.collect()
|
|
424
416
|
deltempfiles()
|
|
425
417
|
if hasattr(apsw, "leak_check"):
|
|
@@ -4875,6 +4867,8 @@ class APSW(unittest.TestCase):
|
|
|
4875
4867
|
|
|
4876
4868
|
def testClosingChecks(self):
|
|
4877
4869
|
"Check closed connection/blob/cursor is correctly detected"
|
|
4870
|
+
if sys.platform == "emscripten":
|
|
4871
|
+
self.skipTest("pyodide crashes")
|
|
4878
4872
|
cur = self.db.cursor()
|
|
4879
4873
|
rowid = curnext(
|
|
4880
4874
|
cur.execute("create table foo(x blob); insert into foo values(zeroblob(98765)); select rowid from foo")
|
|
@@ -4882,7 +4876,7 @@ class APSW(unittest.TestCase):
|
|
|
4882
4876
|
blob = self.db.blob_open("main", "foo", "x", rowid, True)
|
|
4883
4877
|
blob.close()
|
|
4884
4878
|
nargs = self.blob_nargs
|
|
4885
|
-
for func in [x for x in dir(blob) if not x.startswith("__") and x not in ("close", "aclose")]:
|
|
4879
|
+
for func in [x for x in dir(blob) if not x.startswith("__") and x not in ("close", "aclose", "closed")]:
|
|
4886
4880
|
args = ("one", "two", "three")[: nargs.get(func, 0)]
|
|
4887
4881
|
try:
|
|
4888
4882
|
getattr(blob, func)(*args)
|
|
@@ -6150,7 +6144,7 @@ class APSW(unittest.TestCase):
|
|
|
6150
6144
|
"order": ("closed",),
|
|
6151
6145
|
},
|
|
6152
6146
|
"APSWBlob": {
|
|
6153
|
-
"skip": ("dealloc", "dealloc_mutex", "init", "close", "close_internal", "tp_repr", "bool", "aclose"),
|
|
6147
|
+
"skip": ("dealloc", "dealloc_mutex", "init", "close", "close_internal", "tp_repr", "bool", "aclose", "closed"),
|
|
6154
6148
|
"req": {"closed": "CHECK_BLOB_CLOSED"},
|
|
6155
6149
|
"order": ("use", "closed"),
|
|
6156
6150
|
},
|
|
@@ -6967,6 +6961,12 @@ class APSW(unittest.TestCase):
|
|
|
6967
6961
|
self.assertEqual(blobro.read(), b"\x00" * 98765)
|
|
6968
6962
|
blobro.seek(-3, 2)
|
|
6969
6963
|
self.assertEqual(blobro.read(), b"\x00" * 3)
|
|
6964
|
+
blobro.seek(0)
|
|
6965
|
+
x=blobro.read()
|
|
6966
|
+
blobro.seek(0)
|
|
6967
|
+
self.assertEqual(blobro.readall(), x)
|
|
6968
|
+
self.assertEqual(b"", blobro.read())
|
|
6969
|
+
self.assertEqual(b"", blobro.readall())
|
|
6970
6970
|
# check types
|
|
6971
6971
|
self.assertRaises(TypeError, blobro.read, "foo")
|
|
6972
6972
|
self.assertRaises(TypeError, blobro.tell, "foo")
|
|
@@ -6989,6 +6989,7 @@ class APSW(unittest.TestCase):
|
|
|
6989
6989
|
self.assertRaises(apsw.ReadOnlyError, blobro.close)
|
|
6990
6990
|
# check can't work on closed blob
|
|
6991
6991
|
self.assertRaises(ValueError, blobro.read)
|
|
6992
|
+
self.assertRaises(ValueError, blobro.readall)
|
|
6992
6993
|
self.assertRaises(ValueError, blobro.read_into, b"ab")
|
|
6993
6994
|
self.assertRaises(ValueError, blobro.seek, 0, 0)
|
|
6994
6995
|
self.assertRaises(ValueError, blobro.tell)
|
|
@@ -7063,7 +7064,7 @@ class APSW(unittest.TestCase):
|
|
|
7063
7064
|
blobrw.seek(0, 0)
|
|
7064
7065
|
self.assertEqual(blobrw.read(7), b"abcdefg")
|
|
7065
7066
|
blobrw.seek(50, 0)
|
|
7066
|
-
blobrw.write(b"hijkl")
|
|
7067
|
+
self.assertEqual(5, blobrw.write(b"hijkl"))
|
|
7067
7068
|
blobrw.seek(-98765, 2)
|
|
7068
7069
|
self.assertEqual(blobrw.read(55), b"abcdefg" + b"\x00" * 43 + b"hijkl")
|
|
7069
7070
|
self.assertRaises(TypeError, blobrw.write, 12)
|
|
@@ -7090,21 +7091,93 @@ class APSW(unittest.TestCase):
|
|
|
7090
7091
|
self.assertRaises(apsw.SQLError, blobro.reopen, 0x1FFFFFFFF)
|
|
7091
7092
|
blobro.close()
|
|
7092
7093
|
|
|
7093
|
-
def
|
|
7094
|
-
"Ensure blob
|
|
7095
|
-
|
|
7096
|
-
|
|
7097
|
-
|
|
7098
|
-
|
|
7099
|
-
|
|
7100
|
-
|
|
7101
|
-
|
|
7102
|
-
|
|
7103
|
-
|
|
7104
|
-
|
|
7105
|
-
|
|
7106
|
-
|
|
7107
|
-
|
|
7094
|
+
def testBlobExpiredError(self):
|
|
7095
|
+
"Ensure blob errors are handled well"
|
|
7096
|
+
self.db.execute("""
|
|
7097
|
+
create table ioerror (x, blob);
|
|
7098
|
+
insert into ioerror (rowid,x,blob)
|
|
7099
|
+
values (2,3,x'deadbeefbaadf00d'), (3,3,x'deadbeefbaadf00d');""")
|
|
7100
|
+
blobro = self.db.blob_open("main", "ioerror", "blob", 2, False)
|
|
7101
|
+
blobrw = self.db.blob_open("main", "ioerror", "blob", 3, True)
|
|
7102
|
+
self.assertEqual(blobro.length(), 8)
|
|
7103
|
+
self.assertEqual(blobrw.length(), 8)
|
|
7104
|
+
blobro.read(4)
|
|
7105
|
+
blobrw.read(4)
|
|
7106
|
+
blobrw.write(b"X")
|
|
7107
|
+
self.assertEqual(blobro.tell(), 4)
|
|
7108
|
+
self.assertEqual(blobrw.tell(), 5)
|
|
7109
|
+
# Do a SQL write which cause blobs to become invalid
|
|
7110
|
+
self.db.execute("update ioerror set blob='fsdfdsfasd' where x=3")
|
|
7111
|
+
self.assertRaises(apsw.AbortError, blobro.read)
|
|
7112
|
+
self.assertRaises(apsw.AbortError, blobro.readinto, bytearray(10))
|
|
7113
|
+
self.assertRaises(apsw.AbortError, blobrw.write, b"Y")
|
|
7114
|
+
self.assertRaises(apsw.AbortError, blobrw.write, b"Z")
|
|
7115
|
+
self.assertRaises(apsw.AbortError, blobro.readall)
|
|
7116
|
+
self.assertRaises(apsw.AbortError, blobrw.readall)
|
|
7117
|
+
self.assertRaises(apsw.AbortError, blobro.read, 1)
|
|
7118
|
+
|
|
7119
|
+
def testBlobIOBase(self):
|
|
7120
|
+
"blob conformance with io.RawIOBase"
|
|
7121
|
+
|
|
7122
|
+
rowids=self.db.execute("""
|
|
7123
|
+
CREATE TABLE victim(x);
|
|
7124
|
+
INSERT INTO victim VALUES (randomblob(16383)) RETURNING rowid;
|
|
7125
|
+
INSERT INTO victim VALUES (randomblob(16383)) RETURNING rowid;
|
|
7126
|
+
""").get
|
|
7127
|
+
|
|
7128
|
+
blobro = self.db.blob_open("main", "victim", "x", rowids[0], False)
|
|
7129
|
+
blobrw = self.db.blob_open("main", "victim", "x", rowids[1], True)
|
|
7130
|
+
|
|
7131
|
+
for name in dir(io.RawIOBase):
|
|
7132
|
+
match name:
|
|
7133
|
+
case "close" | "read" | "write" | "seek" | "tell" | "readall" | "readinto":
|
|
7134
|
+
# covered in tests above
|
|
7135
|
+
pass
|
|
7136
|
+
case _ if name.startswith("_"):
|
|
7137
|
+
pass
|
|
7138
|
+
case "closed":
|
|
7139
|
+
self.assertFalse(blobro.closed)
|
|
7140
|
+
self.assertFalse(blobrw.closed)
|
|
7141
|
+
case "fileno":
|
|
7142
|
+
self.assertRaises(OSError, blobro.fileno)
|
|
7143
|
+
self.assertRaises(OSError, blobrw.fileno)
|
|
7144
|
+
case "flush":
|
|
7145
|
+
self.assertIsNone(blobro.flush())
|
|
7146
|
+
self.assertIsNone(blobrw.flush())
|
|
7147
|
+
case "isatty":
|
|
7148
|
+
self.assertFalse(blobro.isatty())
|
|
7149
|
+
self.assertFalse(blobrw.isatty())
|
|
7150
|
+
case "readable" | "seekable":
|
|
7151
|
+
self.assertTrue(blobro.readable())
|
|
7152
|
+
self.assertTrue(blobrw.readable())
|
|
7153
|
+
self.assertTrue(blobro.seekable())
|
|
7154
|
+
self.assertTrue(blobrw.seekable())
|
|
7155
|
+
case "readline" | "readlines" | "writelines" | "truncate":
|
|
7156
|
+
# pyodide gets a fatal internal error on these
|
|
7157
|
+
if sys.platform == "emscripten":
|
|
7158
|
+
self.skipTest("pyodide crashes")
|
|
7159
|
+
self.assertRaises(io.UnsupportedOperation, blobro.readline)
|
|
7160
|
+
self.assertRaises(io.UnsupportedOperation, blobrw.readline)
|
|
7161
|
+
self.assertRaises(io.UnsupportedOperation, blobro.readlines)
|
|
7162
|
+
self.assertRaises(io.UnsupportedOperation, blobrw.readlines)
|
|
7163
|
+
self.assertRaises(io.UnsupportedOperation, blobro.writelines)
|
|
7164
|
+
self.assertRaises(io.UnsupportedOperation, blobrw.writelines)
|
|
7165
|
+
self.assertRaises(io.UnsupportedOperation, blobro.truncate)
|
|
7166
|
+
self.assertRaises(io.UnsupportedOperation, blobrw.truncate)
|
|
7167
|
+
case "writable":
|
|
7168
|
+
self.assertFalse(blobro.writable())
|
|
7169
|
+
self.assertTrue(blobrw.writable())
|
|
7170
|
+
case _:
|
|
7171
|
+
raise NotImplementedError
|
|
7172
|
+
|
|
7173
|
+
blobro.close()
|
|
7174
|
+
blobrw.close()
|
|
7175
|
+
self.assertTrue(blobro.closed)
|
|
7176
|
+
self.assertTrue(blobrw.closed)
|
|
7177
|
+
|
|
7178
|
+
self.assertIsInstance(blobro, io.RawIOBase)
|
|
7179
|
+
self.assertIsInstance(blobrw, io.RawIOBase)
|
|
7180
|
+
|
|
7108
7181
|
|
|
7109
7182
|
def testAutovacuumPages(self):
|
|
7110
7183
|
self.assertRaises(TypeError, self.db.autovacuum_pages)
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
# stubs and documentation.
|
|
11
11
|
|
|
12
12
|
import functools
|
|
13
|
-
import inspect
|
|
14
|
-
import threading
|
|
15
|
-
import unittest
|
|
16
13
|
import importlib.resources
|
|
14
|
+
import inspect
|
|
15
|
+
import io
|
|
17
16
|
import json
|
|
18
|
-
|
|
19
17
|
import queue
|
|
20
|
-
|
|
18
|
+
import threading
|
|
19
|
+
import unittest
|
|
20
|
+
from typing import Any, Callable, Literal
|
|
21
21
|
|
|
22
22
|
import apsw
|
|
23
23
|
import apsw.aio
|
|
@@ -245,6 +245,14 @@ class AsyncMeta(unittest.TestCase):
|
|
|
245
245
|
if klass == "Connection" and member in {"vtab_config", "vtab_on_conflict"}:
|
|
246
246
|
return "value"
|
|
247
247
|
raise
|
|
248
|
+
except io.UnsupportedOperation:
|
|
249
|
+
if klass == "Blob" and member in {"readline", "readlines", "truncate", "writelines"}:
|
|
250
|
+
return "value" if send else "async"
|
|
251
|
+
raise
|
|
252
|
+
except OSError:
|
|
253
|
+
if (klass, member) == ("Blob", "fileno"):
|
|
254
|
+
return "value"
|
|
255
|
+
raise
|
|
248
256
|
|
|
249
257
|
def testMetaJson(self):
|
|
250
258
|
apsw.async_controller.set(SimpleController)
|
|
@@ -335,7 +343,6 @@ class AsyncMeta(unittest.TestCase):
|
|
|
335
343
|
"aclose",
|
|
336
344
|
"__exit__",
|
|
337
345
|
"__aexit__",
|
|
338
|
-
"finish",
|
|
339
346
|
}
|
|
340
347
|
|
|
341
348
|
pre = {"__aexit__": "__aenter__", "__exit__": "__enter__", "__next__": "__iter__", "__anext__": "__aiter__"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: apsw-sqlite3mc
|
|
3
|
-
Version: 3.53.
|
|
3
|
+
Version: 3.53.4.0
|
|
4
4
|
Summary: SQLite3 Multiple Ciphers combined with Another Python SQLite Wrapper
|
|
5
5
|
Home-page: https://github.com/utelle/apsw-sqlite3mc
|
|
6
6
|
Author: Ulrich Telle
|
|
@@ -90,7 +90,7 @@ Setting the key on a new database is the only change needed to your code.
|
|
|
90
90
|
|
|
91
91
|
>>> import apsw
|
|
92
92
|
>>> print(apsw.mc_version)
|
|
93
|
-
SQLite3 Multiple Ciphers 2.
|
|
93
|
+
SQLite3 Multiple Ciphers 2.4.0
|
|
94
94
|
>>> con = apsw.Connection("database.sqlite3")
|
|
95
95
|
>>> con.pragma("key", "my secret passphrase")
|
|
96
96
|
ok
|
|
@@ -21,6 +21,8 @@ https://sqlite.org/sqlar/zip/sqlar-src-20180107193712-4824e73896.zip 1980460 63b
|
|
|
21
21
|
https://github.com/madler/zlib/releases/download/v1.3.2/zlib132.zip 1616754 e8bf55f3017aa181690990cb58a994e77885da140609fc8f94abe9b65d2cae28 6b35b981f73425dc5f142cbee457f078d42240c022c804982849b962f1d1e2c6
|
|
22
22
|
|
|
23
23
|
# SQLite releases
|
|
24
|
+
https://sqlite.org/2026/sqlite-autoconf-3530400.tar.gz 3283177 0e9483900e92cd5de8fd48d16bf9200145a61f7fd5be542a5ac81d8a9516eb9c 454e45f61c6bd75b7420e7190732dea03ce6639c63ada47bbc592f67fc340338
|
|
25
|
+
https://sqlite.org/2026/sqlite-src-3530400.zip 14557315 d18fa15aec74d8c17e1463f861095adc01b5ad190256acb4f91d22f0368d232b b834d474b9b393d85a9e3ee4cc11f1329e007e9376a424ee740796f5c4bda3a8
|
|
24
26
|
https://sqlite.org/2026/sqlite-autoconf-3530300.tar.gz 3282443 c917d7db16648ec95f714974ace5e5dcf46b7dc70e26600a0a102a3141125db0 98f2b3f3c11be6a03ea32346937b032c2472ebbd7a716bed36ca2f5693e7ce8b
|
|
25
27
|
https://sqlite.org/2026/sqlite-src-3530300.zip 14537772 bb80bf8a3bffc19241ce8aba5a4bc74e9c3980013cb0b5f0f0976a99516942af 2daecfa16e3b19e058dc2e2cb717b80ade361e0315aa5376c3619f66aa81e181
|
|
26
28
|
https://sqlite.org/2026/sqlite-autoconf-3530200.tar.gz 3279926 588ad51949419a56ebe81fe56193d510c559eb94c9a57748387860b5d3069316 025328da165109f48abccc6e7478508060804412bed2bd81d47e98ba1b72983b
|