sqlite-utils 3.38__py3-none-any.whl → 3.39__py3-none-any.whl

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.
sqlite_utils/cli.py CHANGED
@@ -1,7 +1,7 @@
1
1
  import base64
2
2
  import click
3
3
  from click_default_group import DefaultGroup # type: ignore
4
- from datetime import datetime
4
+ from datetime import datetime, timezone
5
5
  import hashlib
6
6
  import pathlib
7
7
  from runpy import run_module
@@ -962,7 +962,7 @@ def insert_upsert_implementation(
962
962
  db = sqlite_utils.Database(path)
963
963
  _load_extensions(db, load_extension)
964
964
  if functions:
965
- _register_functions(db, functions)
965
+ _register_functions_from_multiple(db, functions)
966
966
  if (delimiter or quotechar or sniff or no_headers) and not tsv:
967
967
  csv = True
968
968
  if (nl + csv + tsv) >= 2:
@@ -1370,7 +1370,9 @@ def upsert(
1370
1370
  @click.argument("file", type=click.File("rb"), required=True)
1371
1371
  @click.option("--batch-size", type=int, default=100, help="Commit every X records")
1372
1372
  @click.option(
1373
- "--functions", help="Python code defining one or more custom SQL functions"
1373
+ "--functions",
1374
+ help="Python code or file path defining custom SQL functions",
1375
+ multiple=True,
1374
1376
  )
1375
1377
  @import_options
1376
1378
  @load_extension_option
@@ -1759,7 +1761,9 @@ def drop_view(path, view, ignore, load_extension):
1759
1761
  help="Named :parameters for SQL query",
1760
1762
  )
1761
1763
  @click.option(
1762
- "--functions", help="Python code defining one or more custom SQL functions"
1764
+ "--functions",
1765
+ help="Python code or file path defining custom SQL functions",
1766
+ multiple=True,
1763
1767
  )
1764
1768
  @load_extension_option
1765
1769
  def query(
@@ -1796,7 +1800,7 @@ def query(
1796
1800
  db.register_fts4_bm25()
1797
1801
 
1798
1802
  if functions:
1799
- _register_functions(db, functions)
1803
+ _register_functions_from_multiple(db, functions)
1800
1804
 
1801
1805
  _execute_query(
1802
1806
  db,
@@ -1824,7 +1828,9 @@ def query(
1824
1828
  )
1825
1829
  @click.argument("sql")
1826
1830
  @click.option(
1827
- "--functions", help="Python code defining one or more custom SQL functions"
1831
+ "--functions",
1832
+ help="Python code or file path defining custom SQL functions",
1833
+ multiple=True,
1828
1834
  )
1829
1835
  @click.option(
1830
1836
  "--attach",
@@ -1996,7 +2002,7 @@ def memory(
1996
2002
  db.register_fts4_bm25()
1997
2003
 
1998
2004
  if functions:
1999
- _register_functions(db, functions)
2005
+ _register_functions_from_multiple(db, functions)
2000
2006
 
2001
2007
  if return_db:
2002
2008
  return db
@@ -3203,8 +3209,12 @@ FILE_COLUMNS = {
3203
3209
  "ctime": lambda p: p.stat().st_ctime,
3204
3210
  "mtime_int": lambda p: int(p.stat().st_mtime),
3205
3211
  "ctime_int": lambda p: int(p.stat().st_ctime),
3206
- "mtime_iso": lambda p: datetime.utcfromtimestamp(p.stat().st_mtime).isoformat(),
3207
- "ctime_iso": lambda p: datetime.utcfromtimestamp(p.stat().st_ctime).isoformat(),
3212
+ "mtime_iso": lambda p: datetime.fromtimestamp(p.stat().st_mtime, timezone.utc)
3213
+ .replace(tzinfo=None)
3214
+ .isoformat(),
3215
+ "ctime_iso": lambda p: datetime.fromtimestamp(p.stat().st_ctime, timezone.utc)
3216
+ .replace(tzinfo=None)
3217
+ .isoformat(),
3208
3218
  "size": lambda p: p.stat().st_size,
3209
3219
  "stem": lambda p: p.stem,
3210
3220
  "suffix": lambda p: p.suffix,
@@ -3281,6 +3291,13 @@ def _load_extensions(db, load_extension):
3281
3291
 
3282
3292
  def _register_functions(db, functions):
3283
3293
  # Register any Python functions as SQL functions:
3294
+ # Check if this is a file path
3295
+ if "\n" not in functions and functions.endswith(".py"):
3296
+ try:
3297
+ functions = pathlib.Path(functions).read_text()
3298
+ except FileNotFoundError:
3299
+ raise click.ClickException("File not found: {}".format(functions))
3300
+
3284
3301
  sqlite3.enable_callback_tracebacks(True)
3285
3302
  globals = {}
3286
3303
  try:
@@ -3291,3 +3308,12 @@ def _register_functions(db, functions):
3291
3308
  for name, value in globals.items():
3292
3309
  if callable(value) and not name.startswith("_"):
3293
3310
  db.register_function(value, name=name)
3311
+
3312
+
3313
+ def _register_functions_from_multiple(db, functions_list):
3314
+ """Register functions from multiple --functions arguments."""
3315
+ if not functions_list:
3316
+ return
3317
+ for functions in functions_list:
3318
+ if isinstance(functions, str) and functions.strip():
3319
+ _register_functions(db, functions)
sqlite_utils/db.py CHANGED
@@ -237,36 +237,43 @@ if pd:
237
237
 
238
238
  class AlterError(Exception):
239
239
  "Error altering table"
240
+
240
241
  pass
241
242
 
242
243
 
243
244
  class NoObviousTable(Exception):
244
245
  "Could not tell which table this operation refers to"
246
+
245
247
  pass
246
248
 
247
249
 
248
250
  class NoTable(Exception):
249
251
  "Specified table does not exist"
252
+
250
253
  pass
251
254
 
252
255
 
253
256
  class BadPrimaryKey(Exception):
254
257
  "Table does not have a single obvious primary key"
258
+
255
259
  pass
256
260
 
257
261
 
258
262
  class NotFoundError(Exception):
259
263
  "Record not found"
264
+
260
265
  pass
261
266
 
262
267
 
263
268
  class PrimaryKeyRequired(Exception):
264
269
  "Primary key needs to be specified"
270
+
265
271
  pass
266
272
 
267
273
 
268
274
  class InvalidColumns(Exception):
269
275
  "Specified columns do not exist"
276
+
270
277
  pass
271
278
 
272
279
 
@@ -368,7 +375,7 @@ class Database:
368
375
  pm.hook.prepare_connection(conn=self.conn)
369
376
  self.strict = strict
370
377
 
371
- def close(self):
378
+ def close(self) -> None:
372
379
  "Close the SQLite connection, and the underlying database file"
373
380
  self.conn.close()
374
381
 
@@ -3203,7 +3210,7 @@ class Table(Queryable):
3203
3210
  :param not_null: Set of strings specifying columns that should be ``NOT NULL``.
3204
3211
  :param defaults: Dictionary specifying default values for specific columns.
3205
3212
  :param hash_id: Name of a column to create and use as a primary key, where the
3206
- value of thet primary key will be derived as a SHA1 hash of the other column values
3213
+ value of that primary key will be derived as a SHA1 hash of the other column values
3207
3214
  in the record. ``hash_id="id"`` is a common column name used for this.
3208
3215
  :param alter: Boolean, should any missing columns be added automatically?
3209
3216
  :param ignore: Boolean, if a record already exists with this primary key, ignore this insert.
@@ -3852,7 +3859,7 @@ def jsonify_if_needed(value):
3852
3859
 
3853
3860
 
3854
3861
  def resolve_extracts(
3855
- extracts: Optional[Union[Dict[str, str], List[str], Tuple[str]]]
3862
+ extracts: Optional[Union[Dict[str, str], List[str], Tuple[str]]],
3856
3863
  ) -> dict:
3857
3864
  if extracts is None:
3858
3865
  extracts = {}
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: sqlite-utils
3
- Version: 3.38
3
+ Version: 3.39
4
4
  Summary: CLI tool and Python library for manipulating SQLite databases
5
5
  Home-page: https://github.com/simonw/sqlite-utils
6
6
  Author: Simon Willison
@@ -15,22 +15,21 @@ Classifier: Intended Audience :: Developers
15
15
  Classifier: Intended Audience :: Science/Research
16
16
  Classifier: Intended Audience :: End Users/Desktop
17
17
  Classifier: Topic :: Database
18
- Classifier: License :: OSI Approved :: Apache Software License
19
- Classifier: Programming Language :: Python :: 3.8
20
- Classifier: Programming Language :: Python :: 3.9
21
18
  Classifier: Programming Language :: Python :: 3.10
22
19
  Classifier: Programming Language :: Python :: 3.11
23
20
  Classifier: Programming Language :: Python :: 3.12
24
21
  Classifier: Programming Language :: Python :: 3.13
25
- Requires-Python: >=3.8
22
+ Classifier: Programming Language :: Python :: 3.14
23
+ Requires-Python: >=3.10
26
24
  Description-Content-Type: text/markdown
27
25
  License-File: LICENSE
28
26
  Requires-Dist: sqlite-fts4
29
- Requires-Dist: click
27
+ Requires-Dist: click>=8.3.1
30
28
  Requires-Dist: click-default-group>=1.2.3
31
29
  Requires-Dist: tabulate
32
30
  Requires-Dist: python-dateutil
33
31
  Requires-Dist: pluggy
32
+ Requires-Dist: pip
34
33
  Provides-Extra: test
35
34
  Requires-Dist: pytest; extra == "test"
36
35
  Requires-Dist: black>=24.1.1; extra == "test"
@@ -54,6 +53,18 @@ Provides-Extra: flake8
54
53
  Requires-Dist: flake8; extra == "flake8"
55
54
  Provides-Extra: tui
56
55
  Requires-Dist: trogon; extra == "tui"
56
+ Dynamic: author
57
+ Dynamic: classifier
58
+ Dynamic: description
59
+ Dynamic: description-content-type
60
+ Dynamic: home-page
61
+ Dynamic: license
62
+ Dynamic: license-file
63
+ Dynamic: project-url
64
+ Dynamic: provides-extra
65
+ Dynamic: requires-dist
66
+ Dynamic: requires-python
67
+ Dynamic: summary
57
68
 
58
69
  # sqlite-utils
59
70
 
@@ -1,15 +1,15 @@
1
1
  sqlite_utils/__init__.py,sha256=eyDK-5KOo-ARS3i0JcuxGiJmk5T-58Z1p_bhACbBrGc,201
2
2
  sqlite_utils/__main__.py,sha256=8hDtWlaFZK24KhfNq_ZKgtXqYHsDQDetukOCMlsbW0Q,59
3
- sqlite_utils/cli.py,sha256=r1cQ70T1KE-0va-ob-AC76Rr81SaSeEVOKp3FAbyPHM,89832
4
- sqlite_utils/db.py,sha256=6minoeWeXkdVS7XwFUUPymePwYtOokwrVIn0qZ1HiI0,148509
3
+ sqlite_utils/cli.py,sha256=aFaRae_sFxpYXwivUqPTkkUWamcqOB-GpDaz2nWzIBg,90639
4
+ sqlite_utils/db.py,sha256=wMKAYDTr9LshEfd4prvHdKigIwcEWcx1sA-i5IR4pV0,148525
5
5
  sqlite_utils/hookspecs.py,sha256=NFA0BFZ8WUhnI_NRz4oFVDcomQYlguuAgUCBKAN792o,395
6
6
  sqlite_utils/plugins.py,sha256=V5nXD4r0o1wSbIHHOAiUBBV66ZOfKVnywKfZzCUqdsA,771
7
7
  sqlite_utils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  sqlite_utils/recipes.py,sha256=_npzti0nPV6XxvMj69Ca4QF-pXwZZQp_f_VY3i7pQDs,1687
9
9
  sqlite_utils/utils.py,sha256=PRqoITtqmaUI7xzyB2exaTPg6oXbTMhGDzld7srNOG4,17099
10
- sqlite_utils-3.38.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
11
- sqlite_utils-3.38.dist-info/METADATA,sha256=12ik5_GloHZ2sO5GCbvFjzQVU1NG_zubIMPfF6V35k4,7540
12
- sqlite_utils-3.38.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
13
- sqlite_utils-3.38.dist-info/entry_points.txt,sha256=33jbVHROlRBNhoXoSI-QI2rN6JDkJIkKIX7P5sNIWdY,54
14
- sqlite_utils-3.38.dist-info/top_level.txt,sha256=_dw_n5BWKUEtCYB2DTlmPMQfdRZSuFsmRQe2ZhNYwnQ,13
15
- sqlite_utils-3.38.dist-info/RECORD,,
10
+ sqlite_utils-3.39.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
11
+ sqlite_utils-3.39.dist-info/METADATA,sha256=Ytv9XEkJTpIkRgP_UdDpkXW6wp0281JYyJ2wBuaDICs,7714
12
+ sqlite_utils-3.39.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
13
+ sqlite_utils-3.39.dist-info/entry_points.txt,sha256=33jbVHROlRBNhoXoSI-QI2rN6JDkJIkKIX7P5sNIWdY,54
14
+ sqlite_utils-3.39.dist-info/top_level.txt,sha256=_dw_n5BWKUEtCYB2DTlmPMQfdRZSuFsmRQe2ZhNYwnQ,13
15
+ sqlite_utils-3.39.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5