solentware-base 5.4__tar.gz → 5.5.2__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.
- {solentware_base-5.4/solentware_base.egg-info → solentware_base-5.5.2}/PKG-INFO +2 -2
- {solentware_base-5.4 → solentware_base-5.5.2}/pyproject.toml +2 -2
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/__init__.py +1 -1
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/apsw_database.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/apswdu_database.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/berkeleydbdu_database.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/bsddb3du_database.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/__init__.py +1 -1
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/_database.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/_databasedu.py +19 -11
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/_db.py +14 -1
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/_db_tkinter.py +28 -11
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/_dbdu.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/_dbdu_tkinter.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/_dpt.py +7 -6
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/_lmdb.py +22 -11
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/_lmdbdu.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/_nosql.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/_nosqldu.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/_sqlite.py +51 -38
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/_sqlitedu.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/bytebit.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/constants.py +2 -1
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/cursor.py +3 -3
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/filespec.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/recordsetcursor.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/segmentsize.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/tree.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/db_tkinterdu_database.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/dpt_database.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/dptdu_database.py +2 -1
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/dptfastload_database.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/gnu_database.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/gnu_module.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/gnudu_database.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/lmdbdu_database.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/modulequery.py +2 -1
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/ndbm_module.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/ndbmdu_database.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/sqlite3_database.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/sqlite3du_database.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/tools/base_3_to_4.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/tools/base_3_to_4_db.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/tools/base_3_to_4_sqlite.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/tools/berkeleydb_du_splice_fix.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/tools/create_database.py +1 -1
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/unqlite_database.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/unqlitedu_database.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/vedis_database.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/vedisdu_database.py +1 -0
- {solentware_base-5.4 → solentware_base-5.5.2/solentware_base.egg-info}/PKG-INFO +2 -2
- {solentware_base-5.4 → solentware_base-5.5.2}/LICENCE +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/MANIFEST.in +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/README +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/setup.cfg +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/berkeleydb_database.py +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/bsddb3_database.py +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/_bytebit.py +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/find.py +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/findvalues.py +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/merge.py +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/record.py +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/recordset.py +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/recordsetbasecursor.py +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/sortsequential.py +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/where.py +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/core/wherevalues.py +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/db_tcl.py +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/db_tkinter_database.py +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/lmdb_database.py +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/ndbm_database.py +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/tools/__init__.py +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/tools/compare_dpt_tape_files.py +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/tools/sqlite_table_name_upgrade.py +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/tools/traverse_dpt_tape_files.py +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/tools/ui_base_3_to_4.py +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base.egg-info/SOURCES.txt +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base.egg-info/dependency_links.txt +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/solentware_base.egg-info/top_level.txt +0 -0
- {solentware_base-5.4 → solentware_base-5.5.2}/tox.ini +0 -0
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: solentware-base
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.5.2
|
|
4
4
|
Summary: Bitmapped record number databases.
|
|
5
5
|
Author-email: Roger Marsh <roger.marsh@solentware.co.uk>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
7
7
|
Project-URL: Homepage, http://www.solentware.co.uk
|
|
8
8
|
Project-URL: Repository, https://github.com/RogerMarsh/solentware-base.git
|
|
9
9
|
Project-URL: Bug Tracker, https://github.com/RogerMarsh/solentware-base/issues
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
11
10
|
Classifier: Programming Language :: Python :: 3.10
|
|
12
11
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
14
|
Classifier: Operating System :: OS Independent
|
|
15
15
|
Classifier: Topic :: Database
|
|
16
16
|
Classifier: Intended Audience :: Developers
|
|
@@ -10,16 +10,16 @@ line-length = 79
|
|
|
10
10
|
|
|
11
11
|
[project]
|
|
12
12
|
name = "solentware-base"
|
|
13
|
-
version = "5.
|
|
13
|
+
version = "5.5.2"
|
|
14
14
|
authors = [
|
|
15
15
|
{ name="Roger Marsh", email="roger.marsh@solentware.co.uk" },
|
|
16
16
|
]
|
|
17
17
|
description = "Bitmapped record number databases."
|
|
18
18
|
classifiers = [
|
|
19
|
-
"Programming Language :: Python :: 3.9",
|
|
20
19
|
"Programming Language :: Python :: 3.10",
|
|
21
20
|
"Programming Language :: Python :: 3.11",
|
|
22
21
|
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
23
|
"Operating System :: OS Independent",
|
|
24
24
|
"Topic :: Database",
|
|
25
25
|
"Intended Audience :: Developers",
|
|
@@ -9,6 +9,7 @@ deferred updates is so different there is no equivalent separate module for
|
|
|
9
9
|
DPT.
|
|
10
10
|
|
|
11
11
|
"""
|
|
12
|
+
|
|
12
13
|
from . import _database
|
|
13
14
|
from .segmentsize import SegmentSize
|
|
14
15
|
from .constants import SECONDARY
|
|
@@ -249,17 +250,24 @@ class Database(_database.Database):
|
|
|
249
250
|
writer = self.merge_writer(file, field)
|
|
250
251
|
merger = merge.Merge(index_directory)
|
|
251
252
|
commit_count = None
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
if commit_count:
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
253
|
+
try:
|
|
254
|
+
for commit_count, item in enumerate(merger.sorter()):
|
|
255
|
+
if not commit_count % commit_limit:
|
|
256
|
+
if commit_count:
|
|
257
|
+
writer.close_cursor()
|
|
258
|
+
self.commit()
|
|
259
|
+
self.deferred_update_housekeeping()
|
|
260
|
+
yield commit_count
|
|
261
|
+
self.start_transaction()
|
|
262
|
+
writer.make_new_cursor()
|
|
263
|
+
writer.write(item)
|
|
264
|
+
writer.close_cursor()
|
|
265
|
+
finally:
|
|
266
|
+
# An exception may leave some reader files open.
|
|
267
|
+
# A 'ResourceWarning: unclosed file <io.TextIOWrapper ...>'
|
|
268
|
+
# message in *_merge_import tests revealed this.
|
|
269
|
+
for reader in merger.readers.values():
|
|
270
|
+
reader.file.close()
|
|
263
271
|
if commit_count is not None:
|
|
264
272
|
self.commit()
|
|
265
273
|
self.deferred_update_housekeeping()
|
|
@@ -18,6 +18,7 @@ Berkeley DB 4.6 is not compatible with berkeleydb, but can be accessed by
|
|
|
18
18
|
the _db_tkinter module, a sibling of _db (this module).
|
|
19
19
|
|
|
20
20
|
"""
|
|
21
|
+
|
|
21
22
|
import os
|
|
22
23
|
from ast import literal_eval
|
|
23
24
|
import bisect
|
|
@@ -310,8 +311,10 @@ class Database(_database.Database):
|
|
|
310
311
|
self.dbenv.log_set_config(dbe.DB_LOG_AUTO_REMOVE, 1)
|
|
311
312
|
except AttributeError as exc:
|
|
312
313
|
if not _openbsd_platform:
|
|
314
|
+
self.dbenv.close()
|
|
313
315
|
raise
|
|
314
316
|
if "'log_set_config'" not in str(exc):
|
|
317
|
+
self.dbenv.close()
|
|
315
318
|
raise
|
|
316
319
|
if gbytes or bytes_:
|
|
317
320
|
self.dbenv.set_cachesize(gbytes, bytes_)
|
|
@@ -399,6 +402,7 @@ class Database(_database.Database):
|
|
|
399
402
|
)
|
|
400
403
|
except:
|
|
401
404
|
self.table[CONTROL_FILE] = None
|
|
405
|
+
self.dbenv.close()
|
|
402
406
|
raise
|
|
403
407
|
for file, specification in self.specification.items():
|
|
404
408
|
if file not in files:
|
|
@@ -415,6 +419,7 @@ class Database(_database.Database):
|
|
|
415
419
|
)
|
|
416
420
|
except:
|
|
417
421
|
self.table[file] = None
|
|
422
|
+
self.dbenv.close()
|
|
418
423
|
raise
|
|
419
424
|
self.ebm_control[file] = ExistenceBitmapControl(
|
|
420
425
|
file, self, dbe, db_create
|
|
@@ -431,6 +436,7 @@ class Database(_database.Database):
|
|
|
431
436
|
)
|
|
432
437
|
except:
|
|
433
438
|
self.segment_table[file] = None
|
|
439
|
+
self.dbenv.close()
|
|
434
440
|
raise
|
|
435
441
|
fieldprops = specification[FIELDS]
|
|
436
442
|
for field, fieldname in fields.items():
|
|
@@ -463,8 +469,10 @@ class Database(_database.Database):
|
|
|
463
469
|
": unexpected file type or format')",
|
|
464
470
|
)
|
|
465
471
|
):
|
|
472
|
+
self.dbenv.close()
|
|
466
473
|
raise
|
|
467
474
|
if access_method is not dbe.DB_HASH:
|
|
475
|
+
self.dbenv.close()
|
|
468
476
|
raise
|
|
469
477
|
|
|
470
478
|
# Accept existing DB_BTREE database if DB_HASH was in the
|
|
@@ -481,10 +489,12 @@ class Database(_database.Database):
|
|
|
481
489
|
)
|
|
482
490
|
except:
|
|
483
491
|
self.table[secondary] = None
|
|
492
|
+
self.dbenv.close()
|
|
484
493
|
raise
|
|
485
494
|
|
|
486
495
|
except:
|
|
487
496
|
self.table[secondary] = None
|
|
497
|
+
self.dbenv.close()
|
|
488
498
|
raise
|
|
489
499
|
if db_create: # and files:
|
|
490
500
|
self.table[CONTROL_FILE].put(
|
|
@@ -1038,7 +1048,10 @@ class Database(_database.Database):
|
|
|
1038
1048
|
recnums = self._get_segment_record_numbers(file, segment_key)
|
|
1039
1049
|
if isinstance(recnums, list):
|
|
1040
1050
|
discard = bisect.bisect_left(recnums, record_number)
|
|
1041
|
-
if
|
|
1051
|
+
if (
|
|
1052
|
+
discard < len(recnums)
|
|
1053
|
+
and recnums[discard] == record_number
|
|
1054
|
+
):
|
|
1042
1055
|
del recnums[discard]
|
|
1043
1056
|
count = len(recnums)
|
|
1044
1057
|
if count < 2:
|
|
@@ -15,6 +15,7 @@ In particular on OpenBSD 7.3 where the default Python is 3.10 and 4.6.21
|
|
|
15
15
|
is the version of Berkeley DB.
|
|
16
16
|
|
|
17
17
|
"""
|
|
18
|
+
|
|
18
19
|
import os
|
|
19
20
|
from ast import literal_eval
|
|
20
21
|
import bisect
|
|
@@ -332,16 +333,20 @@ class Database(_database.Database):
|
|
|
332
333
|
1
|
|
333
334
|
].decode()
|
|
334
335
|
)
|
|
335
|
-
|
|
336
|
-
self.
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
336
|
+
try:
|
|
337
|
+
if self._use_specification_items is not None:
|
|
338
|
+
self.specification.is_consistent_with(
|
|
339
|
+
{
|
|
340
|
+
k: v
|
|
341
|
+
for k, v in spec_from_db.items()
|
|
342
|
+
if k in self._use_specification_items
|
|
343
|
+
}
|
|
344
|
+
)
|
|
345
|
+
else:
|
|
346
|
+
self.specification.is_consistent_with(spec_from_db)
|
|
347
|
+
except:
|
|
348
|
+
tcl_tk_call((self.dbenv, "close"))
|
|
349
|
+
raise
|
|
345
350
|
segment_size = literal_eval(
|
|
346
351
|
tcl_tk_call((control, "get", SEGMENT_SIZE_BYTES_KEY))[0][
|
|
347
352
|
1
|
|
@@ -352,6 +357,7 @@ class Database(_database.Database):
|
|
|
352
357
|
self._real_segment_size_bytes = False
|
|
353
358
|
if segment_size != self.segment_size_bytes:
|
|
354
359
|
self._real_segment_size_bytes = segment_size
|
|
360
|
+
tcl_tk_call((self.dbenv, "close"))
|
|
355
361
|
raise self.SegmentSizeError(
|
|
356
362
|
"".join(
|
|
357
363
|
(
|
|
@@ -368,6 +374,7 @@ class Database(_database.Database):
|
|
|
368
374
|
# Assume equivalent to not a DBNoSuchFileError exception if path
|
|
369
375
|
# exists.
|
|
370
376
|
if fnfd and os.path.exists(fnfd):
|
|
377
|
+
tcl_tk_call((self.dbenv, "close"))
|
|
371
378
|
raise
|
|
372
379
|
db_create = True
|
|
373
380
|
options = ["-create"]
|
|
@@ -492,6 +499,7 @@ class Database(_database.Database):
|
|
|
492
499
|
self.table[CONTROL_FILE] = tcl_tk_call(tuple(command))
|
|
493
500
|
except TclError:
|
|
494
501
|
self.table[CONTROL_FILE] = None
|
|
502
|
+
tcl_tk_call((self.dbenv, "close"))
|
|
495
503
|
raise
|
|
496
504
|
for file, specification in self.specification.items():
|
|
497
505
|
if file not in files:
|
|
@@ -520,6 +528,7 @@ class Database(_database.Database):
|
|
|
520
528
|
self.table[file] = tcl_tk_call(tuple(command))
|
|
521
529
|
except TclError:
|
|
522
530
|
self.table[file] = None
|
|
531
|
+
tcl_tk_call((self.dbenv, "close"))
|
|
523
532
|
raise
|
|
524
533
|
self.ebm_control[file] = ExistenceBitmapControl(
|
|
525
534
|
file, self, dbe, db_create
|
|
@@ -547,6 +556,7 @@ class Database(_database.Database):
|
|
|
547
556
|
self.segment_table[file] = tcl_tk_call(tuple(command))
|
|
548
557
|
except TclError:
|
|
549
558
|
self.segment_table[file] = None
|
|
559
|
+
tcl_tk_call((self.dbenv, "close"))
|
|
550
560
|
raise
|
|
551
561
|
fieldprops = specification[FIELDS]
|
|
552
562
|
for field, fieldname in fields.items():
|
|
@@ -593,8 +603,10 @@ class Database(_database.Database):
|
|
|
593
603
|
)
|
|
594
604
|
)
|
|
595
605
|
):
|
|
606
|
+
tcl_tk_call((self.dbenv, "close"))
|
|
596
607
|
raise
|
|
597
608
|
if access_method != "-hash":
|
|
609
|
+
tcl_tk_call((self.dbenv, "close"))
|
|
598
610
|
raise
|
|
599
611
|
|
|
600
612
|
# Accept existing DB_BTREE database if DB_HASH was in the
|
|
@@ -616,10 +628,12 @@ class Database(_database.Database):
|
|
|
616
628
|
self.table[secondary] = tcl_tk_call(tuple(command))
|
|
617
629
|
except:
|
|
618
630
|
self.table[secondary] = None
|
|
631
|
+
tcl_tk_call((self.dbenv, "close"))
|
|
619
632
|
raise
|
|
620
633
|
|
|
621
634
|
except:
|
|
622
635
|
self.table[secondary] = None
|
|
636
|
+
tcl_tk_call((self.dbenv, "close"))
|
|
623
637
|
raise
|
|
624
638
|
if db_create: # and files:
|
|
625
639
|
command = [self.table[CONTROL_FILE], "put"]
|
|
@@ -1323,7 +1337,10 @@ class Database(_database.Database):
|
|
|
1323
1337
|
recnums = self._get_segment_record_numbers(file, segment_key)
|
|
1324
1338
|
if isinstance(recnums, list):
|
|
1325
1339
|
discard = bisect.bisect_left(recnums, record_number)
|
|
1326
|
-
if
|
|
1340
|
+
if (
|
|
1341
|
+
discard < len(recnums)
|
|
1342
|
+
and recnums[discard] == record_number
|
|
1343
|
+
):
|
|
1327
1344
|
del recnums[discard]
|
|
1328
1345
|
count = len(recnums)
|
|
1329
1346
|
if count < 2:
|
|
@@ -2,17 +2,18 @@
|
|
|
2
2
|
# Copyright 2019 Roger Marsh
|
|
3
3
|
# Licence: See LICENCE (BSD licence)
|
|
4
4
|
|
|
5
|
-
"""Access a DPT database with the
|
|
5
|
+
"""Access a DPT database with the dpt_dbms module.
|
|
6
6
|
|
|
7
7
|
The database will have been created from the application's customization
|
|
8
8
|
of the filespec.FileSpec class.
|
|
9
9
|
|
|
10
10
|
"""
|
|
11
|
+
|
|
11
12
|
import os
|
|
12
13
|
from ast import literal_eval
|
|
13
14
|
import re
|
|
14
15
|
|
|
15
|
-
from
|
|
16
|
+
from dpt_dbms import dptapi
|
|
16
17
|
|
|
17
18
|
from . import _database
|
|
18
19
|
from . import filespec
|
|
@@ -420,7 +421,7 @@ class Database(_database.Database):
|
|
|
420
421
|
return self.table[file].get_primary_record(key)
|
|
421
422
|
|
|
422
423
|
def encode_record_number(self, key):
|
|
423
|
-
"""Return repr(key) because this is
|
|
424
|
+
"""Return repr(key) because this is dpt_dbms version.
|
|
424
425
|
|
|
425
426
|
Typically used to convert primary key, a record number, to secondary
|
|
426
427
|
index format.
|
|
@@ -429,7 +430,7 @@ class Database(_database.Database):
|
|
|
429
430
|
return repr(key)
|
|
430
431
|
|
|
431
432
|
def decode_record_number(self, skey):
|
|
432
|
-
"""Return literal_eval(skey) because this is
|
|
433
|
+
"""Return literal_eval(skey) because this is dpt_dbms version.
|
|
433
434
|
|
|
434
435
|
Typically used to convert secondary index reference to primary record,
|
|
435
436
|
a str(int), to a record number.
|
|
@@ -438,7 +439,7 @@ class Database(_database.Database):
|
|
|
438
439
|
return literal_eval(skey)
|
|
439
440
|
|
|
440
441
|
def encode_record_selector(self, key):
|
|
441
|
-
"""Return key because this is
|
|
442
|
+
"""Return key because this is dpt_dbms version.
|
|
442
443
|
|
|
443
444
|
Typically used to convert a key being used to search a secondary index
|
|
444
445
|
to the form held on the database.
|
|
@@ -818,7 +819,7 @@ class Database(_database.Database):
|
|
|
818
819
|
yield value
|
|
819
820
|
dvcursor.Advance()
|
|
820
821
|
else:
|
|
821
|
-
dvcursor.
|
|
822
|
+
dvcursor.GotoFirst()
|
|
822
823
|
while dvcursor.Accessible():
|
|
823
824
|
value = dvcursor.GetCurrentValue().ExtractString()
|
|
824
825
|
if valuespec.apply_pattern_and_set_filters_to_value(value):
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
# Licence: See LICENCE (BSD licence)
|
|
4
4
|
|
|
5
5
|
"""Access a Symas Lightning Memory-Mapped Database (LMMD) database."""
|
|
6
|
+
|
|
6
7
|
import os
|
|
7
8
|
from ast import literal_eval
|
|
8
9
|
import bisect
|
|
@@ -275,6 +276,7 @@ class Database(_database.Database):
|
|
|
275
276
|
)
|
|
276
277
|
except:
|
|
277
278
|
self.table[DESIGN_FILE] = None
|
|
279
|
+
dbenv.close()
|
|
278
280
|
raise
|
|
279
281
|
try:
|
|
280
282
|
self.table[CONTROL_FILE] = _Datastore(
|
|
@@ -284,6 +286,7 @@ class Database(_database.Database):
|
|
|
284
286
|
)
|
|
285
287
|
except:
|
|
286
288
|
self.table[CONTROL_FILE] = None
|
|
289
|
+
dbenv.close()
|
|
287
290
|
raise
|
|
288
291
|
if files is None:
|
|
289
292
|
files = self.specification.keys()
|
|
@@ -309,6 +312,7 @@ class Database(_database.Database):
|
|
|
309
312
|
)
|
|
310
313
|
except:
|
|
311
314
|
self.segment_table[file] = None
|
|
315
|
+
dbenv.close()
|
|
312
316
|
raise
|
|
313
317
|
for field, fieldname in fields.items():
|
|
314
318
|
if fieldname is None:
|
|
@@ -373,16 +377,20 @@ class Database(_database.Database):
|
|
|
373
377
|
self.end_read_only_transaction()
|
|
374
378
|
self.table[DESIGN_FILE].close_datastore()
|
|
375
379
|
spec_from_db = literal_eval(spec_from_db.decode())
|
|
376
|
-
|
|
377
|
-
self.
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
380
|
+
try:
|
|
381
|
+
if self._use_specification_items is not None:
|
|
382
|
+
self.specification.is_consistent_with(
|
|
383
|
+
{
|
|
384
|
+
k: v
|
|
385
|
+
for k, v in spec_from_db.items()
|
|
386
|
+
if k in self._use_specification_items
|
|
387
|
+
}
|
|
388
|
+
)
|
|
389
|
+
else:
|
|
390
|
+
self.specification.is_consistent_with(spec_from_db)
|
|
391
|
+
except:
|
|
392
|
+
self.dbenv.close()
|
|
393
|
+
raise
|
|
386
394
|
segment_size = literal_eval(segment_size.decode())
|
|
387
395
|
if self._real_segment_size_bytes is not False:
|
|
388
396
|
self.segment_size_bytes = self._real_segment_size_bytes
|
|
@@ -1108,7 +1116,10 @@ class Database(_database.Database):
|
|
|
1108
1116
|
recnums = self._get_segment_record_numbers(file, segment_key)
|
|
1109
1117
|
if isinstance(recnums, list):
|
|
1110
1118
|
discard = bisect.bisect_left(recnums, record_number)
|
|
1111
|
-
if
|
|
1119
|
+
if (
|
|
1120
|
+
discard < len(recnums)
|
|
1121
|
+
and recnums[discard] == record_number
|
|
1122
|
+
):
|
|
1112
1123
|
del recnums[discard]
|
|
1113
1124
|
count = len(recnums)
|
|
1114
1125
|
if count < 2:
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
When using sqlite3 the Python version must be 3.6 or later.
|
|
8
8
|
|
|
9
9
|
"""
|
|
10
|
+
|
|
10
11
|
import os
|
|
11
12
|
from ast import literal_eval
|
|
12
13
|
import re
|
|
@@ -172,45 +173,64 @@ class Database(_database.Database):
|
|
|
172
173
|
if self.database_file is not None:
|
|
173
174
|
dbenv = dbe.Connection(self.database_file)
|
|
174
175
|
cursor = dbenv.cursor()
|
|
175
|
-
|
|
176
|
-
(
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
"== ?",
|
|
184
|
-
)
|
|
176
|
+
cursor.execute(
|
|
177
|
+
" ".join(
|
|
178
|
+
(
|
|
179
|
+
"select name from sqlite_master",
|
|
180
|
+
"where type == 'table' and name == ?",
|
|
181
|
+
)
|
|
182
|
+
),
|
|
183
|
+
(CONTROL_FILE,),
|
|
185
184
|
)
|
|
186
|
-
|
|
185
|
+
if cursor.fetchall():
|
|
186
|
+
statement = " ".join(
|
|
187
|
+
(
|
|
188
|
+
"select",
|
|
189
|
+
SQLITE_VALUE_COLUMN,
|
|
190
|
+
"from",
|
|
191
|
+
CONTROL_FILE,
|
|
192
|
+
"where",
|
|
193
|
+
CONTROL_FILE,
|
|
194
|
+
"== ?",
|
|
195
|
+
)
|
|
196
|
+
)
|
|
187
197
|
cursor.execute(statement, (SPECIFICATION_KEY,))
|
|
188
198
|
rsk = cursor.fetchall()
|
|
189
|
-
except Exception:
|
|
190
|
-
pass
|
|
191
|
-
try:
|
|
192
199
|
cursor.execute(statement, (SEGMENT_SIZE_BYTES_KEY,))
|
|
193
200
|
rssbk = cursor.fetchall()
|
|
194
|
-
except Exception:
|
|
195
|
-
pass
|
|
196
201
|
if rsk is not None and rssbk is not None:
|
|
197
202
|
spec_from_db = literal_eval(rsk[0][0])
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
203
|
+
|
|
204
|
+
# This 'try ... except ...' prevents 7 of the 16 ERROR reports
|
|
205
|
+
# produced, ignoring tests in test___do_database_tasks, on
|
|
206
|
+
# Microsoft Windows when run by
|
|
207
|
+
# 'py -3.13 -m unittest -k test_deferred_update'.
|
|
208
|
+
# The expected exception is FileSpecError but catch all to stay
|
|
209
|
+
# as close as possible to original code.
|
|
210
|
+
try:
|
|
211
|
+
if self._use_specification_items is not None:
|
|
212
|
+
self.specification.is_consistent_with(
|
|
213
|
+
{
|
|
214
|
+
k: v
|
|
215
|
+
for k, v in spec_from_db.items()
|
|
216
|
+
if k in self._use_specification_items
|
|
217
|
+
}
|
|
218
|
+
)
|
|
219
|
+
else:
|
|
220
|
+
self.specification.is_consistent_with(spec_from_db)
|
|
221
|
+
except:
|
|
222
|
+
cursor.close()
|
|
223
|
+
dbenv.close()
|
|
224
|
+
raise
|
|
225
|
+
|
|
208
226
|
segment_size = literal_eval(rssbk[0][0])
|
|
209
227
|
if self._real_segment_size_bytes is not False:
|
|
210
228
|
self.segment_size_bytes = self._real_segment_size_bytes
|
|
211
229
|
self._real_segment_size_bytes = False
|
|
212
230
|
if segment_size != self.segment_size_bytes:
|
|
213
231
|
self._real_segment_size_bytes = segment_size
|
|
232
|
+
cursor.close()
|
|
233
|
+
dbenv.close()
|
|
214
234
|
raise self.SegmentSizeError(
|
|
215
235
|
"".join(
|
|
216
236
|
(
|
|
@@ -220,8 +240,12 @@ class Database(_database.Database):
|
|
|
220
240
|
)
|
|
221
241
|
)
|
|
222
242
|
elif rsk is None and rssbk is not None:
|
|
243
|
+
cursor.close()
|
|
244
|
+
dbenv.close()
|
|
223
245
|
raise DatabaseError("No specification recorded in database")
|
|
224
246
|
elif rsk is not None and rssbk is None:
|
|
247
|
+
cursor.close()
|
|
248
|
+
dbenv.close()
|
|
225
249
|
raise DatabaseError("No segment size recorded in database")
|
|
226
250
|
else:
|
|
227
251
|
dbenv = dbe.Connection(":memory:")
|
|
@@ -1942,18 +1966,7 @@ class Database(_database.Database):
|
|
|
1942
1966
|
"glob ?",
|
|
1943
1967
|
)
|
|
1944
1968
|
)
|
|
1945
|
-
values = (
|
|
1946
|
-
b"".join(
|
|
1947
|
-
(
|
|
1948
|
-
(
|
|
1949
|
-
keystart.encode()
|
|
1950
|
-
if isinstance(keystart, str)
|
|
1951
|
-
else keystart
|
|
1952
|
-
),
|
|
1953
|
-
b"*",
|
|
1954
|
-
)
|
|
1955
|
-
),
|
|
1956
|
-
)
|
|
1969
|
+
values = (keystart + "*",)
|
|
1957
1970
|
db_segment_size_bytes = SegmentSize.db_segment_size_bytes
|
|
1958
1971
|
get_segment_records = self.get_segment_records
|
|
1959
1972
|
cursor = self.dbenv.cursor()
|
|
@@ -14,6 +14,7 @@ Bitarray mostly takes about 4 times longer to do something than bitarray, but
|
|
|
14
14
|
takes about 100 times longer to count set bits.
|
|
15
15
|
|
|
16
16
|
"""
|
|
17
|
+
|
|
17
18
|
# The decision is made here, rather than in solentware_base.__init__, because
|
|
18
19
|
# the DPT specific modules in solentware_base do not need a bit array class as
|
|
19
20
|
# DPT provides it's own bit array handling.
|
|
@@ -10,10 +10,11 @@ See www.dptoolkit.com for details of DPT (No longer exists. The database
|
|
|
10
10
|
interface part of DPT is available at www.solentware.co.uk)
|
|
11
11
|
|
|
12
12
|
"""
|
|
13
|
+
|
|
13
14
|
# Module names of supported database engines (<module>.__name__).
|
|
14
15
|
BERKELEYDB_MODULE = "berkeleydb"
|
|
15
16
|
BSDDB3_MODULE = "bsddb3"
|
|
16
|
-
DPT_MODULE = "
|
|
17
|
+
DPT_MODULE = "dpt_dbms.dptapi"
|
|
17
18
|
SQLITE3_MODULE = "sqlite3"
|
|
18
19
|
APSW_MODULE = "apsw"
|
|
19
20
|
UNQLITE_MODULE = "unqlite"
|
|
@@ -31,9 +31,9 @@ class Cursor:
|
|
|
31
31
|
|
|
32
32
|
For apsw and sqlite3 (SQLite) dbset will be a Connection() object.
|
|
33
33
|
|
|
34
|
-
For
|
|
35
|
-
a RecordSetCursor() or DirectValueCursor(), for records and
|
|
36
|
-
an OpenContext() object.
|
|
34
|
+
For dpt_dbms (DPT) dbset will be a core._dpt.DPTFile() object which
|
|
35
|
+
creates a RecordSetCursor() or DirectValueCursor(), for records and
|
|
36
|
+
indicies, on an OpenContext() object.
|
|
37
37
|
|
|
38
38
|
(A version of the DPT interface is planned where dbset will be an
|
|
39
39
|
OpenContext() object.)
|
|
@@ -9,9 +9,10 @@ external backups should be used. Use dpt_database for transactions,
|
|
|
9
9
|
but adding lots of new records will be a lot slower.
|
|
10
10
|
|
|
11
11
|
"""
|
|
12
|
+
|
|
12
13
|
import os
|
|
13
14
|
|
|
14
|
-
from
|
|
15
|
+
from dpt_dbms import dptapi
|
|
15
16
|
|
|
16
17
|
from .core import _dpt
|
|
17
18
|
from .core.constants import (
|
|
@@ -49,6 +49,7 @@ Berkeley DB (db) is made available via tkinter if the tcl interface to db
|
|
|
49
49
|
is configured in the installed db.
|
|
50
50
|
|
|
51
51
|
"""
|
|
52
|
+
|
|
52
53
|
import sys
|
|
53
54
|
import os
|
|
54
55
|
|
|
@@ -123,7 +124,7 @@ try:
|
|
|
123
124
|
except ImportError: # Not ModuleNotFoundError for Pythons earlier than 3.6
|
|
124
125
|
lmdb = None
|
|
125
126
|
try:
|
|
126
|
-
from
|
|
127
|
+
from dpt_dbms import dptapi
|
|
127
128
|
except ImportError: # Not ModuleNotFoundError for Pythons earlier than 3.6
|
|
128
129
|
dptapi = None
|
|
129
130
|
if _allow("allow_ndbm") or _allow("-n"):
|
|
@@ -61,7 +61,7 @@ try:
|
|
|
61
61
|
except ImportError: # Not ModuleNotFoundError for Pythons earlier than 3.6
|
|
62
62
|
db_tcl = None
|
|
63
63
|
try:
|
|
64
|
-
from
|
|
64
|
+
from dpt_dbms import dptapi
|
|
65
65
|
except ImportError: # Not ModuleNotFoundError for Pythons earlier than 3.6
|
|
66
66
|
dptapi = None
|
|
67
67
|
try:
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: solentware-base
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.5.2
|
|
4
4
|
Summary: Bitmapped record number databases.
|
|
5
5
|
Author-email: Roger Marsh <roger.marsh@solentware.co.uk>
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
7
7
|
Project-URL: Homepage, http://www.solentware.co.uk
|
|
8
8
|
Project-URL: Repository, https://github.com/RogerMarsh/solentware-base.git
|
|
9
9
|
Project-URL: Bug Tracker, https://github.com/RogerMarsh/solentware-base/issues
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
11
10
|
Classifier: Programming Language :: Python :: 3.10
|
|
12
11
|
Classifier: Programming Language :: Python :: 3.11
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
14
|
Classifier: Operating System :: OS Independent
|
|
15
15
|
Classifier: Topic :: Database
|
|
16
16
|
Classifier: Intended Audience :: Developers
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/tools/compare_dpt_tape_files.py
RENAMED
|
File without changes
|
{solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/tools/sqlite_table_name_upgrade.py
RENAMED
|
File without changes
|
{solentware_base-5.4 → solentware_base-5.5.2}/solentware_base/tools/traverse_dpt_tape_files.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|