Skip to content

Commit 36ffcaf

Browse files
committed
table.default_values property, closes #475
Refs #468
1 parent c5f8a2e commit 36ffcaf

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

docs/python-api.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1802,6 +1802,16 @@ The ``.columns_dict`` property returns a dictionary version of the columns with
18021802
>>> db["PlantType"].columns_dict
18031803
{'id': <class 'int'>, 'value': <class 'str'>}
18041804
1805+
.. _python_api_introspection_default_values:
1806+
1807+
.default_values
1808+
---------------
1809+
1810+
The ``.default_values`` property returns a dictionary of default values for each column that has a default::
1811+
1812+
>>> db["table_with_defaults"].default_values
1813+
{'score': 5}
1814+
18051815
.. _python_api_introspection_pks:
18061816
18071817
.pks

sqlite_utils/db.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
progressbar,
1010
find_spatialite,
1111
)
12+
import binascii
1213
from collections import namedtuple
1314
from collections.abc import Mapping
1415
import contextlib
@@ -1458,6 +1459,15 @@ def triggers_dict(self) -> Dict[str, str]:
14581459
"``{trigger_name: sql}`` dictionary of triggers defined on this table."
14591460
return {trigger.name: trigger.sql for trigger in self.triggers}
14601461

1462+
@property
1463+
def default_values(self) -> Dict[str, Any]:
1464+
"``{column_name: default_value}`` dictionary of default values for columns in this table."
1465+
return {
1466+
column.name: _decode_default_value(column.default_value)
1467+
for column in self.columns
1468+
if column.default_value is not None
1469+
}
1470+
14611471
@property
14621472
def strict(self) -> bool:
14631473
"Is this a STRICT table?"
@@ -3527,3 +3537,22 @@ def fix_square_braces(records: Iterable[Dict[str, Any]]):
35273537
}
35283538
else:
35293539
yield record
3540+
3541+
3542+
def _decode_default_value(value):
3543+
if value.startswith("'") and value.endswith("'"):
3544+
# It's a string
3545+
return value[1:-1]
3546+
if value.isdigit():
3547+
# It's an integer
3548+
return int(value)
3549+
if value.startswith("X'") and value.endswith("'"):
3550+
# It's a binary string, stored as hex
3551+
to_decode = value[2:-1]
3552+
return binascii.unhexlify(to_decode)
3553+
# If it is a string containing a floating point number:
3554+
try:
3555+
return float(value)
3556+
except ValueError:
3557+
pass
3558+
return value

tests/test_introspect.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,3 +299,21 @@ def test_table_strict(fresh_db, create_table, expected_strict):
299299
fresh_db.execute(create_table)
300300
table = fresh_db["t"]
301301
assert table.strict == expected_strict
302+
303+
304+
@pytest.mark.parametrize(
305+
"value",
306+
(
307+
1,
308+
1.3,
309+
"foo",
310+
True,
311+
b"binary",
312+
),
313+
)
314+
def test_table_default_values(fresh_db, value):
315+
fresh_db["default_values"].insert(
316+
{"nodefault": 1, "value": value}, defaults={"value": value}
317+
)
318+
default_values = fresh_db["default_values"].default_values
319+
assert default_values == {"value": value}

0 commit comments

Comments
 (0)