solentware-base 5.2.2__tar.gz → 5.3__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.2.2/solentware_base.egg-info → solentware_base-5.3}/PKG-INFO +4 -19
- {solentware_base-5.2.2 → solentware_base-5.3}/pyproject.toml +4 -4
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/_database.py +4 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/_databasedu.py +13 -1
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/_db.py +28 -2
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/_db_tkinter.py +39 -2
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/_dbdu.py +21 -8
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/_dbdu_tkinter.py +21 -8
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/_dpt.py +6 -1
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/_lmdb.py +23 -1
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/_lmdbdu.py +21 -8
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/_nosql.py +31 -3
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/_nosqldu.py +1 -1
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/_sqlite.py +155 -65
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/_sqlitedu.py +1 -1
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/constants.py +1 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/merge.py +8 -5
- {solentware_base-5.2.2 → solentware_base-5.3/solentware_base.egg-info}/PKG-INFO +4 -19
- {solentware_base-5.2.2 → solentware_base-5.3}/LICENCE +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/MANIFEST.in +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/README +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/setup.cfg +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/__init__.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/apsw_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/apswdu_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/berkeleydb_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/berkeleydbdu_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/bsddb3_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/bsddb3du_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/__init__.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/_bytebit.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/bytebit.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/cursor.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/filespec.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/find.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/findvalues.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/record.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/recordset.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/recordsetbasecursor.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/recordsetcursor.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/segmentsize.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/tree.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/where.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/core/wherevalues.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/db_tcl.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/db_tkinter_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/db_tkinterdu_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/dpt_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/dptdu_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/dptfastload_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/gnu_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/gnu_module.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/gnudu_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/lmdb_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/lmdbdu_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/modulequery.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/ndbm_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/ndbm_module.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/ndbmdu_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/sqlite3_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/sqlite3du_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/tools/__init__.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/tools/base_3_to_4.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/tools/base_3_to_4_db.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/tools/base_3_to_4_sqlite.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/tools/berkeleydb_du_splice_fix.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/tools/compare_dpt_tape_files.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/tools/create_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/tools/sqlite_table_name_upgrade.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/tools/traverse_dpt_tape_files.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/tools/ui_base_3_to_4.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/unqlite_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/unqlitedu_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/vedis_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base/vedisdu_database.py +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base.egg-info/SOURCES.txt +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base.egg-info/dependency_links.txt +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/solentware_base.egg-info/top_level.txt +0 -0
- {solentware_base-5.2.2 → solentware_base-5.3}/tox.ini +0 -0
|
@@ -1,28 +1,12 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: solentware-base
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.3
|
|
4
4
|
Summary: Bitmapped record number databases.
|
|
5
5
|
Author-email: Roger Marsh <roger.marsh@solentware.co.uk>
|
|
6
|
-
License:
|
|
7
|
-
Copyright (c) 2009, Roger Marsh
|
|
8
|
-
All rights reserved.
|
|
9
|
-
|
|
10
|
-
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
|
14
|
-
|
|
15
|
-
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
|
16
|
-
|
|
17
|
-
Neither the name of the owner nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
21
|
-
|
|
6
|
+
License-Expression: BSD-3-Clause
|
|
22
7
|
Project-URL: Homepage, http://www.solentware.co.uk
|
|
23
8
|
Project-URL: Repository, https://github.com/RogerMarsh/solentware-base.git
|
|
24
9
|
Project-URL: Bug Tracker, https://github.com/RogerMarsh/solentware-base/issues
|
|
25
|
-
Classifier: License :: OSI Approved :: BSD License
|
|
26
10
|
Classifier: Programming Language :: Python :: 3.9
|
|
27
11
|
Classifier: Programming Language :: Python :: 3.10
|
|
28
12
|
Classifier: Programming Language :: Python :: 3.11
|
|
@@ -32,6 +16,7 @@ Classifier: Topic :: Database
|
|
|
32
16
|
Classifier: Intended Audience :: Developers
|
|
33
17
|
Classifier: Development Status :: 3 - Alpha
|
|
34
18
|
License-File: LICENCE
|
|
19
|
+
Dynamic: license-file
|
|
35
20
|
|
|
36
21
|
=========================================================================
|
|
37
22
|
A bitmapped record number database interface for various database engines
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[build-system]
|
|
2
2
|
requires = [
|
|
3
|
-
"setuptools>=
|
|
3
|
+
"setuptools>=77.0.3",
|
|
4
4
|
"wheel"
|
|
5
5
|
]
|
|
6
6
|
build-backend = "setuptools.build_meta"
|
|
@@ -10,13 +10,12 @@ line-length = 79
|
|
|
10
10
|
|
|
11
11
|
[project]
|
|
12
12
|
name = "solentware-base"
|
|
13
|
-
version = "5.
|
|
13
|
+
version = "5.3"
|
|
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
|
-
"License :: OSI Approved :: BSD License",
|
|
20
19
|
"Programming Language :: Python :: 3.9",
|
|
21
20
|
"Programming Language :: Python :: 3.10",
|
|
22
21
|
"Programming Language :: Python :: 3.11",
|
|
@@ -26,7 +25,8 @@ classifiers = [
|
|
|
26
25
|
"Intended Audience :: Developers",
|
|
27
26
|
"Development Status :: 3 - Alpha",
|
|
28
27
|
]
|
|
29
|
-
license =
|
|
28
|
+
license = "BSD-3-Clause"
|
|
29
|
+
license-files = ["LICENCE"]
|
|
30
30
|
readme = "README"
|
|
31
31
|
|
|
32
32
|
[project.urls]
|
|
@@ -16,7 +16,7 @@ from .bytebit import Bitarray
|
|
|
16
16
|
from . import merge
|
|
17
17
|
|
|
18
18
|
|
|
19
|
-
class DatabaseduError(
|
|
19
|
+
class DatabaseduError(_database.DatabaseError):
|
|
20
20
|
"""Exception for Database class."""
|
|
21
21
|
|
|
22
22
|
|
|
@@ -270,3 +270,15 @@ class Database(_database.Database):
|
|
|
270
270
|
merger = merge.Merge(index_directory)
|
|
271
271
|
for item in merger.sorter():
|
|
272
272
|
yield item
|
|
273
|
+
|
|
274
|
+
def get_merge_import_sort_area(self):
|
|
275
|
+
"""Return database directory.
|
|
276
|
+
|
|
277
|
+
The directory containing database is used for sorting by default,
|
|
278
|
+
subclasses should override as required.
|
|
279
|
+
|
|
280
|
+
There is little point in doing so unless the sort area is then on
|
|
281
|
+
a different drive or mount point.
|
|
282
|
+
|
|
283
|
+
"""
|
|
284
|
+
return self.home_directory
|
|
@@ -34,6 +34,7 @@ from .constants import (
|
|
|
34
34
|
CONTROL_FILE,
|
|
35
35
|
DEFAULT_SEGMENT_SIZE_BYTES,
|
|
36
36
|
SPECIFICATION_KEY,
|
|
37
|
+
APPLICATION_CONTROL_KEY,
|
|
37
38
|
SEGMENT_SIZE_BYTES_KEY,
|
|
38
39
|
SEGMENT_HEADER_LENGTH,
|
|
39
40
|
FIELDS,
|
|
@@ -63,7 +64,7 @@ _openbsd_platform = sys.platform.startswith("openbsd")
|
|
|
63
64
|
del sys
|
|
64
65
|
|
|
65
66
|
|
|
66
|
-
class DatabaseError(
|
|
67
|
+
class DatabaseError(_database.DatabaseError):
|
|
67
68
|
"""Exception for Database class."""
|
|
68
69
|
|
|
69
70
|
|
|
@@ -496,6 +497,9 @@ class Database(_database.Database):
|
|
|
496
497
|
repr(self.segment_size_bytes).encode(),
|
|
497
498
|
txn=self.dbtxn,
|
|
498
499
|
)
|
|
500
|
+
self.table[CONTROL_FILE].put(
|
|
501
|
+
APPLICATION_CONTROL_KEY, repr({}).encode(), txn=self.dbtxn
|
|
502
|
+
)
|
|
499
503
|
self.commit()
|
|
500
504
|
self._dbe = dbe
|
|
501
505
|
|
|
@@ -549,7 +553,10 @@ class Database(_database.Database):
|
|
|
549
553
|
for field in specification[SECONDARY]:
|
|
550
554
|
secondary = SUBFILE_DELIMITER.join((file, field))
|
|
551
555
|
if secondary in self.table:
|
|
552
|
-
|
|
556
|
+
try:
|
|
557
|
+
self.table[secondary].close()
|
|
558
|
+
except AttributeError:
|
|
559
|
+
pass
|
|
553
560
|
self.table[secondary] = None
|
|
554
561
|
for k, dbo in self.table.items():
|
|
555
562
|
if dbo is not None:
|
|
@@ -1760,6 +1767,25 @@ class Database(_database.Database):
|
|
|
1760
1767
|
return super()._generate_database_file_name(name)
|
|
1761
1768
|
return os.path.join(self.home_directory, name)
|
|
1762
1769
|
|
|
1770
|
+
def get_application_control(self):
|
|
1771
|
+
"""Return dict of application control items."""
|
|
1772
|
+
value = self.table[CONTROL_FILE].get(
|
|
1773
|
+
APPLICATION_CONTROL_KEY,
|
|
1774
|
+
txn=self.dbtxn,
|
|
1775
|
+
)
|
|
1776
|
+
if value is not None:
|
|
1777
|
+
return literal_eval(value.decode())
|
|
1778
|
+
return {}
|
|
1779
|
+
|
|
1780
|
+
def set_application_control(self, appcontrol):
|
|
1781
|
+
"""Set dict of application control items."""
|
|
1782
|
+
self.table[CONTROL_FILE].delete(
|
|
1783
|
+
APPLICATION_CONTROL_KEY, txn=self.dbtxn
|
|
1784
|
+
)
|
|
1785
|
+
self.table[CONTROL_FILE].put(
|
|
1786
|
+
APPLICATION_CONTROL_KEY, repr(appcontrol).encode(), txn=self.dbtxn
|
|
1787
|
+
)
|
|
1788
|
+
|
|
1763
1789
|
|
|
1764
1790
|
class Cursor(_cursor.Cursor):
|
|
1765
1791
|
"""Define a cursor on the underlying database engine dbset.
|
|
@@ -33,6 +33,7 @@ from .constants import (
|
|
|
33
33
|
CONTROL_FILE,
|
|
34
34
|
DEFAULT_SEGMENT_SIZE_BYTES,
|
|
35
35
|
SPECIFICATION_KEY,
|
|
36
|
+
APPLICATION_CONTROL_KEY,
|
|
36
37
|
SEGMENT_SIZE_BYTES_KEY,
|
|
37
38
|
SEGMENT_HEADER_LENGTH,
|
|
38
39
|
FIELDS,
|
|
@@ -62,7 +63,7 @@ _openbsd_platform = sys.platform.startswith("openbsd")
|
|
|
62
63
|
del sys
|
|
63
64
|
|
|
64
65
|
|
|
65
|
-
class DatabaseError(
|
|
66
|
+
class DatabaseError(_database.DatabaseError):
|
|
66
67
|
"""Exception for Database class."""
|
|
67
68
|
|
|
68
69
|
|
|
@@ -638,6 +639,11 @@ class Database(_database.Database):
|
|
|
638
639
|
]
|
|
639
640
|
)
|
|
640
641
|
tcl_tk_call(tuple(command))
|
|
642
|
+
command = [self.table[CONTROL_FILE], "put"]
|
|
643
|
+
if self.dbtxn:
|
|
644
|
+
command.extend(["-txn", self.dbtxn])
|
|
645
|
+
command.extend([APPLICATION_CONTROL_KEY, repr({}).encode()])
|
|
646
|
+
tcl_tk_call(tuple(command))
|
|
641
647
|
self.commit()
|
|
642
648
|
|
|
643
649
|
def _run_db_archive(self):
|
|
@@ -713,7 +719,10 @@ class Database(_database.Database):
|
|
|
713
719
|
# careless about deleting closed secondary database DB
|
|
714
720
|
# objects in deferred update mode. Exceptions occur
|
|
715
721
|
# here if that is allowed to happen with the Tcl API.
|
|
716
|
-
|
|
722
|
+
try:
|
|
723
|
+
tcl_tk_call((self.table[secondary], "close"))
|
|
724
|
+
except AttributeError:
|
|
725
|
+
pass
|
|
717
726
|
self.table[secondary] = None
|
|
718
727
|
for k, dbo in self.table.items():
|
|
719
728
|
if dbo is not None:
|
|
@@ -2194,6 +2203,34 @@ class Database(_database.Database):
|
|
|
2194
2203
|
return super()._generate_database_file_name(name)
|
|
2195
2204
|
return os.path.join(self.home_directory, name)
|
|
2196
2205
|
|
|
2206
|
+
def get_application_control(self):
|
|
2207
|
+
"""Return dict of application control items."""
|
|
2208
|
+
command = [self.table[CONTROL_FILE], "get"]
|
|
2209
|
+
if self.dbtxn:
|
|
2210
|
+
command.extend(["-txn", self.dbtxn])
|
|
2211
|
+
command.extend(
|
|
2212
|
+
[
|
|
2213
|
+
APPLICATION_CONTROL_KEY,
|
|
2214
|
+
]
|
|
2215
|
+
)
|
|
2216
|
+
value = tcl_tk_call(tuple(command))
|
|
2217
|
+
if value is not None:
|
|
2218
|
+
return literal_eval(value.decode())
|
|
2219
|
+
return {}
|
|
2220
|
+
|
|
2221
|
+
def set_application_control(self, appcontrol):
|
|
2222
|
+
"""Set dict of application control items."""
|
|
2223
|
+
command = [self.table[CONTROL_FILE], "delete"]
|
|
2224
|
+
if self.dbtxn:
|
|
2225
|
+
command.extend(["-txn", self.dbtxn])
|
|
2226
|
+
command.extend([APPLICATION_CONTROL_KEY])
|
|
2227
|
+
tcl_tk_call(tuple(command))
|
|
2228
|
+
command = [self.table[CONTROL_FILE], "put"]
|
|
2229
|
+
if self.dbtxn:
|
|
2230
|
+
command.extend(["-txn", self.dbtxn])
|
|
2231
|
+
command.extend([APPLICATION_CONTROL_KEY, repr(appcontrol).encode()])
|
|
2232
|
+
tcl_tk_call(tuple(command))
|
|
2233
|
+
|
|
2197
2234
|
|
|
2198
2235
|
class Cursor(_cursor.Cursor):
|
|
2199
2236
|
"""Define a cursor on the underlying database engine dbset.
|
|
@@ -21,7 +21,7 @@ from .recordset import (
|
|
|
21
21
|
from . import _databasedu
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
class DatabaseError(
|
|
24
|
+
class DatabaseError(_databasedu.DatabaseduError):
|
|
25
25
|
"""Exception for Database class."""
|
|
26
26
|
|
|
27
27
|
|
|
@@ -481,7 +481,7 @@ class Database(_databasedu.Database):
|
|
|
481
481
|
assert len(record) == 2
|
|
482
482
|
value, segment = record
|
|
483
483
|
if len(segment) == 6:
|
|
484
|
-
count = b"x00\x01"
|
|
484
|
+
count = b"\x00\x01"
|
|
485
485
|
reference = segment[4:]
|
|
486
486
|
else:
|
|
487
487
|
count = segment[4:6]
|
|
@@ -529,17 +529,23 @@ class Database(_databasedu.Database):
|
|
|
529
529
|
self.prev_key = item[0]
|
|
530
530
|
item_type = item.pop(2)
|
|
531
531
|
if item_type == EXISTING_SEGMENT_REFERENCE:
|
|
532
|
-
self.cursor.put(item[0], b"".join(item[1:]), keylast)
|
|
533
532
|
assert len(item) == 4
|
|
533
|
+
if item[-2] == b"\x00\x01":
|
|
534
|
+
item.pop(-2)
|
|
535
|
+
self.cursor.put(item[0], b"".join(item[1:]), keylast)
|
|
536
|
+
length = len(b"".join(item[1:]))
|
|
537
|
+
assert length == 10 or length == 6
|
|
534
538
|
return
|
|
535
539
|
if int.from_bytes(item[-2], byteorder="big") > 1:
|
|
536
540
|
item[-1] = segment_table.append(
|
|
537
541
|
item[-1], txn=self.database.dbtxn
|
|
538
542
|
).to_bytes(4, byteorder="big")
|
|
539
543
|
assert len(item) == 4
|
|
544
|
+
assert len(b"".join(item[1:])) == 10
|
|
540
545
|
else:
|
|
541
546
|
item.pop(2)
|
|
542
547
|
assert len(item) == 3
|
|
548
|
+
assert len(b"".join(item[1:])) == 6
|
|
543
549
|
self.cursor.put(item[0], b"".join(item[1:]), keylast)
|
|
544
550
|
assert item_type == NEW_SEGMENT_CONTENT
|
|
545
551
|
return
|
|
@@ -547,22 +553,22 @@ class Database(_databasedu.Database):
|
|
|
547
553
|
assert item[2] == NEW_SEGMENT_CONTENT
|
|
548
554
|
del item[2]
|
|
549
555
|
high = read_high_item_in_index(self.cursor)
|
|
550
|
-
|
|
556
|
+
new_segment = make_segment_from_item(item)
|
|
557
|
+
new_segment |= make_segment_from_high(
|
|
551
558
|
high, self.database.dbtxn
|
|
552
559
|
)
|
|
553
|
-
new_segment = make_segment_from_item(item)
|
|
554
|
-
new_segment |= existing_segment
|
|
555
560
|
new_segment.normalize()
|
|
556
561
|
item[-2] = (
|
|
557
562
|
self.database.encode_number_for_sequential_file_dump(
|
|
558
563
|
new_segment.count_records(), 2
|
|
559
564
|
)
|
|
560
565
|
)
|
|
561
|
-
if
|
|
566
|
+
if high[2] == b"\x00\x01":
|
|
562
567
|
item[-1] = segment_table.append(
|
|
563
568
|
new_segment.tobytes(), txn=self.database.dbtxn
|
|
564
569
|
).to_bytes(4, byteorder="big")
|
|
565
570
|
self.cursor.delete()
|
|
571
|
+
assert len(b"".join(item[1:])) == 10
|
|
566
572
|
self.cursor.put(item[0], b"".join(item[1:]), keylast)
|
|
567
573
|
else:
|
|
568
574
|
segment_table.put(
|
|
@@ -572,14 +578,19 @@ class Database(_databasedu.Database):
|
|
|
572
578
|
)
|
|
573
579
|
self.cursor.delete()
|
|
574
580
|
item[-1] = high[-1]
|
|
581
|
+
assert len(b"".join(item[1:])) == 10
|
|
575
582
|
self.cursor.put(item[0], b"".join(item[1:]), keylast)
|
|
576
583
|
assert len(item) == 4
|
|
577
584
|
return
|
|
578
585
|
item_type = item.pop(2)
|
|
579
586
|
if item_type == EXISTING_SEGMENT_REFERENCE:
|
|
587
|
+
assert len(item) == 4
|
|
580
588
|
self.prev_key = item[0]
|
|
589
|
+
if item[-2] == b"\x00\x01":
|
|
590
|
+
item.pop(-2)
|
|
581
591
|
self.cursor.put(item[0], b"".join(item[1:]), keylast)
|
|
582
|
-
|
|
592
|
+
length = len(b"".join(item[1:]))
|
|
593
|
+
assert length == 10 or length == 6
|
|
583
594
|
return
|
|
584
595
|
if int.from_bytes(item[-2], byteorder="big") > 1:
|
|
585
596
|
item[-1] = segment_table.append(
|
|
@@ -587,9 +598,11 @@ class Database(_databasedu.Database):
|
|
|
587
598
|
txn=self.database.dbtxn,
|
|
588
599
|
).to_bytes(4, byteorder="big")
|
|
589
600
|
assert len(item) == 4
|
|
601
|
+
assert len(b"".join(item[1:])) == 10
|
|
590
602
|
else:
|
|
591
603
|
item.pop(2)
|
|
592
604
|
assert len(item) == 3
|
|
605
|
+
assert len(b"".join(item[1:])) == 6
|
|
593
606
|
self.cursor.put(item[0], b"".join(item[1:]), keylast)
|
|
594
607
|
assert item_type == NEW_SEGMENT_CONTENT
|
|
595
608
|
return
|
|
@@ -22,7 +22,7 @@ from .recordset import (
|
|
|
22
22
|
from . import _databasedu
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
class DatabaseError(
|
|
25
|
+
class DatabaseError(_databasedu.DatabaseduError):
|
|
26
26
|
"""Exception for Database class."""
|
|
27
27
|
|
|
28
28
|
|
|
@@ -576,7 +576,7 @@ class Database(_databasedu.Database):
|
|
|
576
576
|
assert len(record) == 1
|
|
577
577
|
value, segment = record[0]
|
|
578
578
|
if len(segment) == 6:
|
|
579
|
-
count = b"x00\x01"
|
|
579
|
+
count = b"\x00\x01"
|
|
580
580
|
reference = segment[4:]
|
|
581
581
|
else:
|
|
582
582
|
count = segment[4:6]
|
|
@@ -664,22 +664,28 @@ class Database(_databasedu.Database):
|
|
|
664
664
|
self.prev_key = item[0]
|
|
665
665
|
item_type = item.pop(2)
|
|
666
666
|
if item_type == EXISTING_SEGMENT_REFERENCE:
|
|
667
|
+
assert len(item) == 4
|
|
668
|
+
if item[-2] == b"\x00\x01":
|
|
669
|
+
item.pop(-2)
|
|
667
670
|
tcl_tk_call(
|
|
668
671
|
tuple(
|
|
669
672
|
self.write_item_to_index
|
|
670
673
|
+ [item[0], b"".join(item[1:])]
|
|
671
674
|
)
|
|
672
675
|
)
|
|
673
|
-
|
|
676
|
+
length = len(b"".join(item[1:]))
|
|
677
|
+
assert length == 10 or length == 6
|
|
674
678
|
return
|
|
675
679
|
if int.from_bytes(item[-2], byteorder="big") > 1:
|
|
676
680
|
item[-1] = tcl_tk_call(
|
|
677
681
|
tuple(self.write_segment_value + [item[-1]])
|
|
678
682
|
).to_bytes(4, byteorder="big")
|
|
679
683
|
assert len(item) == 4
|
|
684
|
+
assert len(b"".join(item[1:])) == 10
|
|
680
685
|
else:
|
|
681
686
|
item.pop(2)
|
|
682
687
|
assert len(item) == 3
|
|
688
|
+
assert len(b"".join(item[1:])) == 6
|
|
683
689
|
tcl_tk_call(
|
|
684
690
|
tuple(
|
|
685
691
|
self.write_item_to_index
|
|
@@ -694,22 +700,22 @@ class Database(_databasedu.Database):
|
|
|
694
700
|
high = read_high_item_in_index(
|
|
695
701
|
self.get_last_record_in_index
|
|
696
702
|
)
|
|
697
|
-
|
|
703
|
+
new_segment = make_segment_from_item(item)
|
|
704
|
+
new_segment |= make_segment_from_high(
|
|
698
705
|
high, self.get_segment_value
|
|
699
706
|
)
|
|
700
|
-
new_segment = make_segment_from_item(item)
|
|
701
|
-
new_segment |= existing_segment
|
|
702
707
|
new_segment.normalize()
|
|
703
708
|
item[-2] = (
|
|
704
709
|
self.database.encode_number_for_sequential_file_dump(
|
|
705
710
|
new_segment.count_records(), 2
|
|
706
711
|
)
|
|
707
712
|
)
|
|
708
|
-
if
|
|
713
|
+
if high[2] == b"\x00\x01":
|
|
709
714
|
item[-1] = tcl_tk_call(
|
|
710
715
|
tuple(self.write_segment_value + [item[-1]])
|
|
711
716
|
).to_bytes(4, byteorder="big")
|
|
712
717
|
tcl_tk_call(tuple(self.delete_index_item))
|
|
718
|
+
assert len(b"".join(item[1:])) == 10
|
|
713
719
|
tcl_tk_call(
|
|
714
720
|
tuple(
|
|
715
721
|
self.write_item_to_index
|
|
@@ -728,6 +734,7 @@ class Database(_databasedu.Database):
|
|
|
728
734
|
)
|
|
729
735
|
tcl_tk_call(tuple(self.delete_index_item))
|
|
730
736
|
item[-1] = high[-1]
|
|
737
|
+
assert len(b"".join(item[1:])) == 10
|
|
731
738
|
tcl_tk_call(
|
|
732
739
|
tuple(
|
|
733
740
|
self.write_item_to_index
|
|
@@ -738,23 +745,29 @@ class Database(_databasedu.Database):
|
|
|
738
745
|
return
|
|
739
746
|
item_type = item.pop(2)
|
|
740
747
|
if item_type == EXISTING_SEGMENT_REFERENCE:
|
|
748
|
+
assert len(item) == 4
|
|
741
749
|
self.prev_key = item[0]
|
|
750
|
+
if item[-2] == b"\x00\x01":
|
|
751
|
+
item.pop(-2)
|
|
742
752
|
tcl_tk_call(
|
|
743
753
|
tuple(
|
|
744
754
|
self.write_item_to_index
|
|
745
755
|
+ [item[0], b"".join(item[1:])]
|
|
746
756
|
)
|
|
747
757
|
)
|
|
748
|
-
|
|
758
|
+
length = len(b"".join(item[1:]))
|
|
759
|
+
assert length == 10 or length == 6
|
|
749
760
|
return
|
|
750
761
|
if int.from_bytes(item[-2], byteorder="big") > 1:
|
|
751
762
|
item[-1] = tcl_tk_call(
|
|
752
763
|
tuple(self.write_segment_value + [item[-1]])
|
|
753
764
|
).to_bytes(4, byteorder="big")
|
|
754
765
|
assert len(item) == 4
|
|
766
|
+
assert len(b"".join(item[1:])) == 10
|
|
755
767
|
else:
|
|
756
768
|
item.pop(2)
|
|
757
769
|
assert len(item) == 3
|
|
770
|
+
assert len(b"".join(item[1:])) == 6
|
|
758
771
|
tcl_tk_call(
|
|
759
772
|
tuple(
|
|
760
773
|
self.write_item_to_index
|
|
@@ -63,7 +63,7 @@ FILE_PARAMETER_LIST = (
|
|
|
63
63
|
SegmentSize.db_segment_size_bytes = TABLE_B_SIZE
|
|
64
64
|
|
|
65
65
|
|
|
66
|
-
class DatabaseError(
|
|
66
|
+
class DatabaseError(_database.DatabaseError):
|
|
67
67
|
"""Raise when an exceptional case is encountered in Database class."""
|
|
68
68
|
|
|
69
69
|
|
|
@@ -1292,6 +1292,11 @@ class DPTFile:
|
|
|
1292
1292
|
# Open the file for normal use.
|
|
1293
1293
|
self.open_existing_file(dbenv)
|
|
1294
1294
|
|
|
1295
|
+
# Check requested fields exist.
|
|
1296
|
+
# A RuntimeError is raised by GetFieldAtts() if field does not exist.
|
|
1297
|
+
for field in self.fields:
|
|
1298
|
+
self.opencontext.GetFieldAtts(field)
|
|
1299
|
+
|
|
1295
1300
|
# Permanent instances for efficient file updates.
|
|
1296
1301
|
self.fieldvalue = dptapi.APIFieldValue()
|
|
1297
1302
|
self._putrecordcopy = dptapi.APIStoreRecordTemplate()
|
|
@@ -18,6 +18,7 @@ from .constants import (
|
|
|
18
18
|
DESIGN_FILE,
|
|
19
19
|
DEFAULT_SEGMENT_SIZE_BYTES,
|
|
20
20
|
SPECIFICATION_KEY,
|
|
21
|
+
APPLICATION_CONTROL_KEY,
|
|
21
22
|
SEGMENT_SIZE_BYTES_KEY,
|
|
22
23
|
SEGMENT_HEADER_LENGTH,
|
|
23
24
|
DEFAULT_MAP_SIZE,
|
|
@@ -38,7 +39,7 @@ from .recordset import (
|
|
|
38
39
|
)
|
|
39
40
|
|
|
40
41
|
|
|
41
|
-
class DatabaseError(
|
|
42
|
+
class DatabaseError(_database.DatabaseError):
|
|
42
43
|
"""Exception for Database class."""
|
|
43
44
|
|
|
44
45
|
|
|
@@ -343,6 +344,7 @@ class Database(_database.Database):
|
|
|
343
344
|
SEGMENT_SIZE_BYTES_KEY,
|
|
344
345
|
repr(self.segment_size_bytes).encode(),
|
|
345
346
|
)
|
|
347
|
+
cursor.put(APPLICATION_CONTROL_KEY, repr({}).encode())
|
|
346
348
|
cursor.close()
|
|
347
349
|
self.table[DESIGN_FILE].close_datastore()
|
|
348
350
|
self.open_database_contexts()
|
|
@@ -387,6 +389,8 @@ class Database(_database.Database):
|
|
|
387
389
|
self._real_segment_size_bytes = False
|
|
388
390
|
if segment_size != self.segment_size_bytes:
|
|
389
391
|
self._real_segment_size_bytes = segment_size
|
|
392
|
+
self.dbenv.close()
|
|
393
|
+
self.dbenv = None
|
|
390
394
|
raise self.SegmentSizeError(
|
|
391
395
|
" ".join(
|
|
392
396
|
(
|
|
@@ -1847,6 +1851,24 @@ class Database(_database.Database):
|
|
|
1847
1851
|
) // DEFAULT_MAP_PAGES
|
|
1848
1852
|
self.dbenv.set_mapsize(self.map_blocks * DEFAULT_MAP_SIZE)
|
|
1849
1853
|
|
|
1854
|
+
def get_application_control(self):
|
|
1855
|
+
"""Return dict of application control items."""
|
|
1856
|
+
value = self.dbtxn.transaction.get(
|
|
1857
|
+
APPLICATION_CONTROL_KEY,
|
|
1858
|
+
db=self.table[DESIGN_FILE].datastore,
|
|
1859
|
+
)
|
|
1860
|
+
if value is not None:
|
|
1861
|
+
return literal_eval(value.decode())
|
|
1862
|
+
return {}
|
|
1863
|
+
|
|
1864
|
+
def set_application_control(self, appcontrol):
|
|
1865
|
+
"""Set dict of application control items."""
|
|
1866
|
+
self.dbtxn.transaction.put(
|
|
1867
|
+
APPLICATION_CONTROL_KEY,
|
|
1868
|
+
repr(appcontrol).encode(),
|
|
1869
|
+
db=self.table[DESIGN_FILE].datastore,
|
|
1870
|
+
)
|
|
1871
|
+
|
|
1850
1872
|
|
|
1851
1873
|
class _DBtxn:
|
|
1852
1874
|
"""Provide a Symas LMMD read-only or read-write transaction instance.
|
|
@@ -19,7 +19,7 @@ from .recordset import (
|
|
|
19
19
|
from . import _databasedu
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
class DatabaseError(
|
|
22
|
+
class DatabaseError(_databasedu.DatabaseduError):
|
|
23
23
|
"""Exception for Database class."""
|
|
24
24
|
|
|
25
25
|
|
|
@@ -530,7 +530,7 @@ class Database(_databasedu.Database):
|
|
|
530
530
|
assert len(record) == 2
|
|
531
531
|
value, segment = record
|
|
532
532
|
if len(segment) == 6:
|
|
533
|
-
count = b"x00\x01"
|
|
533
|
+
count = b"\x00\x01"
|
|
534
534
|
reference = segment[4:]
|
|
535
535
|
else:
|
|
536
536
|
count = segment[4:6]
|
|
@@ -587,17 +587,23 @@ class Database(_databasedu.Database):
|
|
|
587
587
|
self.prev_key = item[0]
|
|
588
588
|
item_type = item.pop(2)
|
|
589
589
|
if item_type == EXISTING_SEGMENT_REFERENCE:
|
|
590
|
-
self.cursor.put(item[0], b"".join(item[1:]))
|
|
591
590
|
assert len(item) == 4
|
|
591
|
+
if item[-2] == b"\x00\x01":
|
|
592
|
+
item.pop(-2)
|
|
593
|
+
self.cursor.put(item[0], b"".join(item[1:]))
|
|
594
|
+
length = len(b"".join(item[1:]))
|
|
595
|
+
assert length == 10 or length == 6
|
|
592
596
|
return
|
|
593
597
|
if int.from_bytes(item[-2], byteorder="big") > 1:
|
|
594
598
|
item[-1] = write_segment_value(
|
|
595
599
|
item[-1], self.segment_cursor
|
|
596
600
|
)
|
|
597
601
|
assert len(item) == 4
|
|
602
|
+
assert len(b"".join(item[1:])) == 10
|
|
598
603
|
else:
|
|
599
604
|
item.pop(2)
|
|
600
605
|
assert len(item) == 3
|
|
606
|
+
assert len(b"".join(item[1:])) == 6
|
|
601
607
|
self.cursor.put(item[0], b"".join(item[1:]))
|
|
602
608
|
assert item_type == NEW_SEGMENT_CONTENT
|
|
603
609
|
return
|
|
@@ -605,22 +611,22 @@ class Database(_databasedu.Database):
|
|
|
605
611
|
assert item[2] == NEW_SEGMENT_CONTENT
|
|
606
612
|
del item[2]
|
|
607
613
|
high = read_high_item_in_index(self.cursor)
|
|
608
|
-
|
|
614
|
+
new_segment = make_segment_from_item(item)
|
|
615
|
+
new_segment |= make_segment_from_high(
|
|
609
616
|
high, self.database.dbtxn.transaction
|
|
610
617
|
)
|
|
611
|
-
new_segment = make_segment_from_item(item)
|
|
612
|
-
new_segment |= existing_segment
|
|
613
618
|
new_segment.normalize()
|
|
614
619
|
item[-2] = (
|
|
615
620
|
self.database.encode_number_for_sequential_file_dump(
|
|
616
621
|
new_segment.count_records(), 2
|
|
617
622
|
)
|
|
618
623
|
)
|
|
619
|
-
if
|
|
624
|
+
if high[2] == b"\x00\x01":
|
|
620
625
|
item[-1] = write_segment_value(
|
|
621
626
|
new_segment.tobytes(), self.segment_cursor
|
|
622
627
|
)
|
|
623
628
|
self.cursor.delete()
|
|
629
|
+
assert len(b"".join(item[1:])) == 10
|
|
624
630
|
self.cursor.put(item[0], b"".join(item[1:]))
|
|
625
631
|
else:
|
|
626
632
|
self.database.dbtxn.transaction.put(
|
|
@@ -630,23 +636,30 @@ class Database(_databasedu.Database):
|
|
|
630
636
|
)
|
|
631
637
|
self.cursor.delete()
|
|
632
638
|
item[-1] = high[-1]
|
|
639
|
+
assert len(b"".join(item[1:])) == 10
|
|
633
640
|
self.cursor.put(item[0], b"".join(item[1:]))
|
|
634
641
|
assert len(item) == 4
|
|
635
642
|
return
|
|
636
643
|
item_type = item.pop(2)
|
|
637
644
|
if item_type == EXISTING_SEGMENT_REFERENCE:
|
|
645
|
+
assert len(item) == 4
|
|
638
646
|
self.prev_key = item[0]
|
|
647
|
+
if item[-2] == b"\x00\x01":
|
|
648
|
+
item.pop(-2)
|
|
639
649
|
self.cursor.put(item[0], b"".join(item[1:]))
|
|
640
|
-
|
|
650
|
+
length = len(b"".join(item[1:]))
|
|
651
|
+
assert length == 10 or length == 6
|
|
641
652
|
return
|
|
642
653
|
if int.from_bytes(item[-2], byteorder="big") > 1:
|
|
643
654
|
item[-1] = write_segment_value(
|
|
644
655
|
item[-1], self.segment_cursor
|
|
645
656
|
)
|
|
646
657
|
assert len(item) == 4
|
|
658
|
+
assert len(b"".join(item[1:])) == 10
|
|
647
659
|
else:
|
|
648
660
|
item.pop(2)
|
|
649
661
|
assert len(item) == 3
|
|
662
|
+
assert len(b"".join(item[1:])) == 6
|
|
650
663
|
self.cursor.put(item[0], b"".join(item[1:]))
|
|
651
664
|
assert item_type == NEW_SEGMENT_CONTENT
|
|
652
665
|
return
|