From 2aab3e82d1053c623ce85dac72659b7e5c164f81 Mon Sep 17 00:00:00 2001 From: Ethan Ho <53266718+ethho@users.noreply.github.com> Date: Sun, 22 Sep 2024 12:16:25 -0500 Subject: [PATCH] Disable hidden attributes (#1091) by default --- datajoint/declare.py | 22 +++++++++-------- datajoint/settings.py | 1 + tests/test_declare.py | 57 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 64 insertions(+), 16 deletions(-) diff --git a/datajoint/declare.py b/datajoint/declare.py index 1c02564a..d813374a 100644 --- a/datajoint/declare.py +++ b/datajoint/declare.py @@ -10,6 +10,7 @@ from .errors import DataJointError, _support_filepath_types, FILEPATH_FEATURE_SWITCH from .attribute_adapter import get_adapter from .condition import translate_attribute +from .settings import config UUID_DATA_TYPE = "binary(16)" MAX_TABLE_NAME_LENGTH = 64 @@ -311,17 +312,18 @@ def declare(full_table_name, definition, context): external_stores, ) = prepare_declare(definition, context) - metadata_attr_sql = [ - "`_{full_table_name}_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP" - ] - attribute_sql.extend( - attr.format( - full_table_name=sha1( - full_table_name.replace("`", "").encode("utf-8") - ).hexdigest() + if config.get("enable_hidden_attributes", False): + metadata_attr_sql = [ + "`_{full_table_name}_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP" + ] + attribute_sql.extend( + attr.format( + full_table_name=sha1( + full_table_name.replace("`", "").encode("utf-8") + ).hexdigest() + ) + for attr in metadata_attr_sql ) - for attr in metadata_attr_sql - ) if not primary_key: raise DataJointError("Table must have a primary key") diff --git a/datajoint/settings.py b/datajoint/settings.py index 4fc7f301..e1779859 100644 --- a/datajoint/settings.py +++ b/datajoint/settings.py @@ -47,6 +47,7 @@ "display.show_tuple_count": True, "database.use_tls": None, "enable_python_native_blobs": True, # python-native/dj0 encoding support + "enable_hidden_attributes": False, "filepath_checksum_size_limit": None, # file size limit for when to disable checksums } ) diff --git a/tests/test_declare.py b/tests/test_declare.py index f848d31c..0b808e56 100644 --- a/tests/test_declare.py +++ b/tests/test_declare.py @@ -3,6 +3,25 @@ import datajoint as dj import inspect from datajoint.declare import declare +from datajoint.settings import config + + +@pytest.fixture(scope="function") +def enable_hidden_attributes(): + orig_config_val = config.get("enable_hidden_attributes") + config["enable_hidden_attributes"] = True + yield + if orig_config_val is not None: + config["enable_hidden_attributes"] = orig_config_val + + +@pytest.fixture(scope="function") +def disable_hidden_attributes(): + orig_config_val = config.get("enable_hidden_attributes") + config["enable_hidden_attributes"] = False + yield + if orig_config_val is not None: + config["enable_hidden_attributes"] = orig_config_val def test_schema_decorator(schema_any): @@ -373,9 +392,35 @@ class Table_With_Underscores(dj.Manual): schema_any(Table_With_Underscores) -def test_hidden_attributes(schema_any): - assert ( - list(Experiment().heading._attributes.keys())[-1].split("_")[2] == "timestamp" - ) - assert any(a.is_hidden for a in Experiment().heading._attributes.values()) - assert not any(a.is_hidden for a in Experiment().heading.attributes.values()) +def test_hidden_attributes_default_value(): + config_val = config.get("enable_hidden_attributes") + assert config_val is not None and not config_val, \ + "Default value for enable_hidden_attributes is not False" + + +def test_hidden_attributes_enabled(enable_hidden_attributes, schema_any): + orig_config_val = config.get("enable_hidden_attributes") + config["enable_hidden_attributes"] = True + + msg = f"{Experiment().heading._attributes=}" + assert any(a.name.endswith("_timestamp") for a in Experiment().heading._attributes.values()), msg + assert any(a.name.startswith("_") for a in Experiment().heading._attributes.values()), msg + assert any(a.is_hidden for a in Experiment().heading._attributes.values()), msg + assert not any(a.is_hidden for a in Experiment().heading.attributes.values()), msg + + if orig_config_val is not None: + config["enable_hidden_attributes"] = orig_config_val + + +def test_hidden_attributes_disabled(disable_hidden_attributes, schema_any): + orig_config_val = config.get("enable_hidden_attributes") + config["enable_hidden_attributes"] = False + + msg = f"{Experiment().heading._attributes=}" + assert not any(a.name.endswith("_timestamp") for a in Experiment().heading._attributes.values()), msg + assert not any(a.name.startswith("_") for a in Experiment().heading._attributes.values()), msg + assert not any(a.is_hidden for a in Experiment().heading._attributes.values()), msg + assert not any(a.is_hidden for a in Experiment().heading.attributes.values()), msg + + if orig_config_val is not None: + config["enable_hidden_attributes"] = orig_config_val