From a90411f1cd0dc8e0d9d4625ad671775490c82c0f Mon Sep 17 00:00:00 2001 From: Dimitri Yatsenko Date: Fri, 23 Jan 2026 21:55:01 -0600 Subject: [PATCH 1/5] fix: remove user input prompts from conn() The low-level `conn()` function should not block execution waiting for user input. Instead, raise DataJointError if credentials are missing. Users should configure credentials via: - datajoint.config['database.user'] - datajoint.config['database.password'] - Or pass user= and password= arguments directly Closes #1343 Co-Authored-By: Claude Opus 4.5 --- src/datajoint/connection.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/datajoint/connection.py b/src/datajoint/connection.py index 43dd43fa8..1445300ed 100644 --- a/src/datajoint/connection.py +++ b/src/datajoint/connection.py @@ -11,7 +11,6 @@ import re import warnings from contextlib import contextmanager -from getpass import getpass from typing import Callable import pymysql as client @@ -110,9 +109,9 @@ def conn( host : str, optional Database hostname. user : str, optional - MySQL username. + Database username. Required if not set in config. password : str, optional - MySQL password. Prompts if not provided. + Database password. Required if not set in config. init_fun : callable, optional Initialization function called after connection. reset : bool, optional @@ -125,15 +124,24 @@ def conn( ------- Connection Persistent database connection. + + Raises + ------ + DataJointError + If user or password is not provided and not set in config. """ if not hasattr(conn, "connection") or reset: host = host if host is not None else config["database.host"] user = user if user is not None else config["database.user"] password = password if password is not None else config["database.password"] if user is None: - user = input("Please enter DataJoint username: ") + raise errors.DataJointError( + "Database user not configured. Set datajoint.config['database.user'] or pass user= argument." + ) if password is None: - password = getpass(prompt="Please enter DataJoint password: ") + raise errors.DataJointError( + "Database password not configured. Set datajoint.config['database.password'] or pass password= argument." + ) init_fun = init_fun if init_fun is not None else config["connection.init_function"] use_tls = use_tls if use_tls is not None else config["database.use_tls"] conn.connection = Connection(host, user, password, None, init_fun, use_tls) From aaf2158cdc26a4eb2a11eb8e6df2153afdaf592d Mon Sep 17 00:00:00 2001 From: Dimitri Yatsenko Date: Fri, 23 Jan 2026 21:56:27 -0600 Subject: [PATCH 2/5] chore: bump version to 2.0.0a23 --- src/datajoint/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/datajoint/version.py b/src/datajoint/version.py index 98a5f2b93..c516748d9 100644 --- a/src/datajoint/version.py +++ b/src/datajoint/version.py @@ -1,4 +1,4 @@ # version bump auto managed by Github Actions: # label_prs.yaml(prep), release.yaml(bump), post_release.yaml(edit) # manually set this version will be eventually overwritten by the above actions -__version__ = "2.0.0a22" +__version__ = "2.0.0a23" From 6a955c13034b5264bccc7e52947c6520001bf4a0 Mon Sep 17 00:00:00 2001 From: Dimitri Yatsenko Date: Fri, 23 Jan 2026 22:01:34 -0600 Subject: [PATCH 3/5] feat: add database.schema_prefix config setting Users can store a project-specific schema prefix in config: dj.config.database.schema_prefix = 'myproject_' schema = dj.Schema(dj.config.database.schema_prefix + 'analysis') Or via environment variable DJ_SCHEMA_PREFIX or datajoint.json. The prefix is not automatically applied, giving users flexibility in their naming conventions. Co-Authored-By: Claude Opus 4.5 --- src/datajoint/settings.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/datajoint/settings.py b/src/datajoint/settings.py index e9b6f6570..88f3c7b71 100644 --- a/src/datajoint/settings.py +++ b/src/datajoint/settings.py @@ -60,6 +60,7 @@ "database.user": "DJ_USER", "database.password": "DJ_PASS", "database.port": "DJ_PORT", + "database.schema_prefix": "DJ_SCHEMA_PREFIX", "loglevel": "DJ_LOG_LEVEL", } @@ -185,6 +186,12 @@ class DatabaseSettings(BaseSettings): port: int = Field(default=3306, validation_alias="DJ_PORT") reconnect: bool = True use_tls: bool | None = None + schema_prefix: str = Field( + default="", + validation_alias="DJ_SCHEMA_PREFIX", + description="Project-specific prefix for schema names. " + "Not automatically applied; use dj.config.database.schema_prefix when creating schemas.", + ) class ConnectionSettings(BaseSettings): From 8ca6b2a146a988f5c6ab5a9dbf77e52fb3512d1e Mon Sep 17 00:00:00 2001 From: Dimitri Yatsenko Date: Fri, 23 Jan 2026 22:07:26 -0600 Subject: [PATCH 4/5] feat: add database.create_tables config setting Users can disable automatic table creation for production mode: dj.config.database.create_tables = False Or via environment variable DJ_CREATE_TABLES or datajoint.json. When False, Schema will raise an error when accessing missing tables instead of creating them. Explicit create_tables=True in Schema() overrides the config setting. Co-Authored-By: Claude Opus 4.5 --- src/datajoint/schemas.py | 10 ++++++---- src/datajoint/settings.py | 7 +++++++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/datajoint/schemas.py b/src/datajoint/schemas.py index 98faa83f2..1878870df 100644 --- a/src/datajoint/schemas.py +++ b/src/datajoint/schemas.py @@ -72,7 +72,8 @@ class Schema: create_schema : bool, optional If False, raise error if schema doesn't exist. Default True. create_tables : bool, optional - If False, raise error when accessing missing tables. Default True. + If False, raise error when accessing missing tables. + Default from ``dj.config.database.create_tables`` (True unless configured). add_objects : dict, optional Additional objects for the declaration context. @@ -93,7 +94,7 @@ def __init__( *, connection: Connection | None = None, create_schema: bool = True, - create_tables: bool = True, + create_tables: bool | None = None, add_objects: dict[str, Any] | None = None, ) -> None: """ @@ -110,7 +111,8 @@ def __init__( create_schema : bool, optional If False, raise error if schema doesn't exist. Default True. create_tables : bool, optional - If False, raise error when accessing missing tables. Default True. + If False, raise error when accessing missing tables. + Default from ``dj.config.database.create_tables`` (True unless configured). add_objects : dict, optional Additional objects for the declaration context. """ @@ -118,7 +120,7 @@ def __init__( self.database = None self.context = context self.create_schema = create_schema - self.create_tables = create_tables + self.create_tables = create_tables if create_tables is not None else config.database.create_tables self.add_objects = add_objects self.declare_list = [] if schema_name: diff --git a/src/datajoint/settings.py b/src/datajoint/settings.py index 88f3c7b71..be06673f3 100644 --- a/src/datajoint/settings.py +++ b/src/datajoint/settings.py @@ -61,6 +61,7 @@ "database.password": "DJ_PASS", "database.port": "DJ_PORT", "database.schema_prefix": "DJ_SCHEMA_PREFIX", + "database.create_tables": "DJ_CREATE_TABLES", "loglevel": "DJ_LOG_LEVEL", } @@ -192,6 +193,12 @@ class DatabaseSettings(BaseSettings): description="Project-specific prefix for schema names. " "Not automatically applied; use dj.config.database.schema_prefix when creating schemas.", ) + create_tables: bool = Field( + default=True, + validation_alias="DJ_CREATE_TABLES", + description="Default for Schema create_tables parameter. " + "Set to False for production mode to prevent automatic table creation.", + ) class ConnectionSettings(BaseSettings): From 460f03edef2ed7f53654994cf335d9d34d2b59cf Mon Sep 17 00:00:00 2001 From: Dimitri Yatsenko Date: Fri, 23 Jan 2026 22:09:13 -0600 Subject: [PATCH 5/5] chore: bump version to 2.0.0a24 Co-Authored-By: Claude Opus 4.5 --- src/datajoint/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/datajoint/version.py b/src/datajoint/version.py index c516748d9..c3800af52 100644 --- a/src/datajoint/version.py +++ b/src/datajoint/version.py @@ -1,4 +1,4 @@ # version bump auto managed by Github Actions: # label_prs.yaml(prep), release.yaml(bump), post_release.yaml(edit) # manually set this version will be eventually overwritten by the above actions -__version__ = "2.0.0a23" +__version__ = "2.0.0a24"