tdfs4ds.config¶
tdfs4ds.config
¶
Configuration loading for tdfs4ds.
Three external configuration sources are supported, applied in this order so that higher-priority sources always win:
- JSON config file — project defaults, searched in order:
./tdfs4ds.json(project-local)-
~/.tdfs4ds/config.json(user-global) -
.envfile — local environment overrides, searched in order: ./.env(project-local)-
~/.tdfs4ds/.env(user-global) OnlyTDFS4DS_*variables are read. Module-config vars are set on thetdfs4dsmodule; pass-through vars (connectionTDFS4DS_TD_*, serve togglesTDFS4DS_SERVE_*,TDFS4DS_SKILLS_FOLDER) are exported toos.environbecause the serve layer reads them from there directly. Unlike the JSON config, credentials are accepted here (add.envto.gitignoreto keep secrets out of source control). -
OS environment variables — prefix
TDFS4DS_, e.g.TDFS4DS_SCHEMA,TDFS4DS_SCHEMA_VIEW,TDFS4DS_DATA_DOMAIN.
Credentials (INSTRUCT_MODEL_API_KEY) are rejected from the JSON config
file to prevent accidental commits; use a .env file or an OS env var.
Full priority chain (highest first): programmatic > OS env var > .env file > JSON config > built-in defaults
_BOOL_VARS
module-attribute
¶
_BOOL_VARS = frozenset({'DISPLAY_LOGS', 'DEBUG_MODE', 'USE_VOLATILE_TABLE', 'BUILD_DATASET_AT_UPLOAD', 'INSTRUCT_MODEL_VERIFY_SSL', 'MCP_TOOL_DISCOVERY', 'QUERY_BAND', 'AGENTIC_FEATURES', 'UPLOAD_DOCUMENT', 'UPLOAD_EXPLAIN', 'UPLOAD_OPTIMIZE_QUERY', 'UPLOAD_VECTOR_INDEXING', 'UPLOAD_CASCADE_REDOCUMENTATION', 'OPIK_VENDOR_TELEMETRY', 'PROCESS_SQL_VERSIONING', 'TIME_MANAGER_DETECT', 'EXPOSED_VIEW_AUTO_ATTACH', 'EXECUTION_RESOURCES', 'LOG_COLOR', 'LOG_PROPAGATE'})
_INT_VARS
module-attribute
¶
_INT_VARS = frozenset({'VARCHAR_SIZE', 'FEATURE_PARTITION_N', 'FEATURE_PARTITION_EACH', 'EMBEDDING_MODEL_DIM', 'EMBEDDING_MODEL_MAX_TOKENS', 'CHROMA_PORT', 'SCHEDULING_MAX_WORKERS', 'MCP_MAX_TOOLS', 'MCP_FALLBACK_MAX_TOOLS', 'EMBEDDING_BATCH_SIZE', 'CREDENTIAL_RENEWAL_ATTEMPTS'})
_FILE_VARS
module-attribute
¶
_FILE_VARS = frozenset({'SCHEMA', 'SCHEMA_VIEW', 'SCHEMA_READONLY', 'DATA_DOMAIN', 'FEATURE_STORE_TIME', 'DISPLAY_LOGS', 'LOG_COLOR', 'LOG_PROPAGATE', 'DEBUG_MODE', 'STORE_FEATURE', 'REGISTER_FEATURE', 'REGISTER_PROCESS', 'USE_VOLATILE_TABLE', 'BUILD_DATASET_AT_UPLOAD', 'QUERY_BAND', 'AGENTIC_FEATURES', 'UPLOAD_DOCUMENT', 'UPLOAD_EXPLAIN', 'UPLOAD_OPTIMIZE_QUERY', 'UPLOAD_VECTOR_INDEXING', 'UPLOAD_CASCADE_REDOCUMENTATION', 'VARCHAR_SIZE', 'FEATURE_PARTITION_N', 'FEATURE_PARTITION_EACH', 'SCHEDULING_MAX_WORKERS', 'TIME_MANAGER_CHECK', 'PROCESS_SQL_VERSIONING', 'TIME_MANAGER_DETECT', 'EXPOSED_VIEW_AUTO_ATTACH', 'EXECUTION_RESOURCES', 'INSTRUCT_MODEL_PROVIDER', 'INSTRUCT_MODEL_URL', 'INSTRUCT_MODEL_MODEL', 'INSTRUCT_MODEL_REGION', 'INSTRUCT_MODEL_AZURE_DEPLOYMENT', 'INSTRUCT_MODEL_AZURE_API_VERSION', 'INSTRUCT_MODEL_GCP_PROJECT', 'INSTRUCT_MODEL_GCP_LOCATION', 'EMBEDDING_MODEL_REGION', 'EMBEDDING_MODEL_AZURE_DEPLOYMENT', 'EMBEDDING_MODEL_AZURE_API_VERSION', 'EMBEDDING_MODEL_GCP_PROJECT', 'EMBEDDING_MODEL_GCP_LOCATION', 'INSTRUCT_MODEL_CLIENT_MODE', 'EMBEDDING_MODEL_CLIENT_MODE', 'INSTRUCT_MODEL_PROXY', 'INSTRUCT_MODEL_VERIFY_SSL', 'INSTRUCT_MODEL_CA_BUNDLE', 'STRUCTURED_OUTPUT_METHOD', 'EMBEDDING_MODEL_PROVIDER', 'EMBEDDING_MODEL_URL', 'EMBEDDING_MODEL_MODEL', 'EMBEDDING_MODEL_PROXY', 'EMBEDDING_MODEL_DIM', 'EMBEDDING_MODEL_MAX_TOKENS', 'EMBEDDING_BATCH_DELAY', 'EMBEDDING_BATCH_SIZE', 'CREDENTIAL_RENEWAL_ATTEMPTS', 'CHROMA_MODE', 'CHROMA_PATH', 'CHROMA_HOST', 'CHROMA_PORT', 'VECTOR_STORE_BACKEND', 'TERADATA_VECTOR_STORE_PREFIX', 'TERADATA_AI_API_TYPE', 'TERADATA_AI_MODEL_NAME', 'TERADATA_AI_REGION', 'TERADATA_AI_API_BASE', 'MCP_SERVER_URL', 'MCP_SERVER_TRANSPORT', 'MCP_SERVER_EDITION', 'MCP_AUTH', 'MCP_USERNAME', 'MCP_SERVER_CA_BUNDLE', 'MCP_MAX_TOOLS', 'MCP_TOOL_DISCOVERY', 'MCP_FALLBACK_MAX_TOOLS', 'TRACING', 'OPIK_PROJECT_NAME', 'OPIK_VENDOR_TELEMETRY'})
_CREDENTIAL_VARS
module-attribute
¶
_CREDENTIAL_VARS = frozenset({'INSTRUCT_MODEL_API_KEY', 'EMBEDDING_MODEL_API_KEY', 'TERADATA_AI_ACCESS_KEY', 'MCP_PASSWORD', 'MCP_SERVER_HEADERS'})
_PASSTHROUGH_ENV_VARS
module-attribute
¶
_PASSTHROUGH_ENV_VARS = frozenset({'TD_HOST', 'TD_USERNAME', 'TD_PASSWORD', 'TD_LOGMECH', 'TD_DATABASE', 'TD_ENCRYPT', 'TD_LOGDATA', 'SERVE_PORT', 'SERVE_BUILD_INDEX', 'SERVE_CHATBOT', 'SERVE_CHATBOT_PORT', 'SERVE_DOCS', 'SERVE_DOCS_PORT', 'SERVE_ROOT_PATH', 'SERVE_MCP_URL', 'SERVE_DEFAULT_VIEW', 'SKILLS_FOLDER', 'VECTOR_STORE_AUTH_BASE_URL', 'VECTOR_STORE_AUTH_AUTH_TOKEN', 'VECTOR_STORE_AUTH_PAT_TOKEN', 'VECTOR_STORE_AUTH_PEM_FILE', 'VECTOR_STORE_AUTH_USERNAME', 'VECTOR_STORE_AUTH_PASSWORD', 'VECTOR_STORE_AUTH_CLIENT_ID'})
_SECRET_SUFFIXES
module-attribute
¶
_JSON_CANDIDATES
module-attribute
¶
_DOTENV_CANDIDATES
module-attribute
¶
_is_placeholder
¶
True when value is a generator placeholder rather than a real value.
_is_secret
¶
True when attr names a credential that must never be written in clear.
_strip_trailing_comment
¶
Drop a trailing # comment from an UNQUOTED .env value.
Only whitespace followed by # starts a comment, so a # inside a
value (common in generated passwords) survives. Quote the value to keep a
literal " #".
_needs_quoting
¶
True when leaving value bare would change what the parser reads back.
Lives next to :func:_parse_dotenv on purpose: the parser defines the
rule this has to satisfy, and a renderer that drifts from its own parser
produces a file that looks right and authenticates with something else.
_render_dotenv_value
¶
Render one value for a .env line, quoting when it matters.
There is no escape syntax in :func:_parse_dotenv, so a value containing
both quote characters cannot be represented; that case is written bare with
a warning rather than silently corrupted.
force_quote is for values whose shape is not known in advance (a credential, typically): quoting one that did not need it is harmless, while failing to quote one that did truncates it at the first " #".
_parse_dotenv
¶
Parse path as a .env file and return a {ATTR: raw_value} dict
for every TDFS4DS_* variable found.
Handles:
- KEY=VALUE
- KEY="VALUE" / KEY='VALUE'
- export KEY=VALUE
- # comments (whole-line and trailing) and blank lines
Trailing-comment rule, matching python-dotenv so a file behaves the same
whichever loader reads it: in an unquoted value, whitespace followed by
# starts a comment and is dropped. A # with no whitespace before it
is part of the value (PASSWORD=abc#def is abc#def), and quoting
keeps everything verbatim (PASSWORD="abc #def") — which is how to
write a value that genuinely contains " #".
This used to keep the comment: PASSWORD=secret # prod became the
literal secret # prod, which then failed authentication somewhere far
away from the file that caused it.
_apply_dotenv
¶
Parse path as a .env file and apply TDFS4DS_* entries.
Module-config vars are set on module; pass-through vars (connection / serve
/ skills — read straight from os.environ by the serve layer) are exported
to os.environ so a .env works regardless of how it is loaded.
_load_config
¶
Called automatically during import tdfs4ds.
Load order (lowest → highest priority): JSON config file → .env file → OS env vars
export_config
¶
Capture the current configuration as a JSON config file or a .env.
Two uses, selected by source:
source='module'(default) — snapshot the running configuration (tdfs4ds.<ATTR>), including anything set in-session. Use it to reproduce a session that works.source='env'— convert theTDFS4DS_*environment variables into a file, whether or not they ever reached the module config.
Parameters¶
path : str or pathlib.Path, optional
Where to write. When None nothing is written and the text is only
returned — inspect it before committing it to disk.
fmt : {'json', 'env'}
'json' writes a tdfs4ds.json that load_config() reads;
'env' writes TDFS4DS_* lines for a .env / container
env-file. Only 'env' can carry connection and Vector Store auth
variables — those are pass-through, never module attributes, so
fmt='json' cannot express them.
include_secrets : bool, default False
Secrets (anything whose name contains PASSWORD / TOKEN / API_KEY /
ACCESS_KEY / SECRET) are written commented out with a placeholder,
so the result is a shareable template. Pass True to write the real
values — then treat the file as a secret. Ignored for fmt='json':
_apply_file rejects credentials from JSON by design, so they are
never written there.
Returns¶
str The file content, whether or not path was given.
Examples¶
tdfs4ds.export_config() # inspect # doctest: +SKIP tdfs4ds.export_config('tdfs4ds.json') # reusable config tdfs4ds.export_config('.env', fmt='env', source='env') # env -> file
patch_dotenv
¶
Set individual TDFS4DS_* variables in an existing .env, in place.
:func:export_config and :func:tdfs4ds.generate_ai_studio_env both
rewrite the whole file, which loses its comments, its ordering and the
commented-out alternatives they deliberately put there. This changes one
line at a time, so a probed value can be recorded into a file a human
maintains.
It is line-based rather than parse-and-rewrite because :func:_parse_dotenv
is lossy for this purpose — it drops comments, ordering and quoting, so it
cannot serve as the read side of a read-modify-write.
Which line is changed, and why:
- The last uncommented occurrence.
_parse_dotenvassigns as it reads, so on a duplicate the last one is what takes effect; patching any other would leave the file saying one thing and meaning another. - Otherwise the first commented-out slot (
#TDFS4DS_X=) is uncommented in place. A generated file offers such slots precisely so that turning one on is an edit. - Otherwise appended, preceded by comment if given.
A commented slot is never uncommented while a live line exists — a
generated file carries commented alternatives next to the live choice
(two MCP_SERVER_URL lines, for instance), and enabling one of those
would silently switch the setting to the alternative.
Parameters¶
path : str or Path
An existing .env. Creating one is :func:export_config's or
:func:tdfs4ds.generate_ai_studio_env's job, not this function's, so a
missing file raises rather than being conjured half-populated.
updates : dict
{'STRUCTURED_OUTPUT_METHOD': 'function_calling'} — keys with or
without the TDFS4DS_ prefix. Values are rendered the way
:func:_coerce reads them back, so None is written as the literal
None (which loads as None), not as an empty line.
comment : str, optional
Provenance note, written as a trailing comment on the line itself.
Say where the value came from and when: a pinned setting that was right
in one session is wrong in another, and a stale pin should be visible
rather than silent.
Trailing rather than above, because the whole line is rewritten on each
call — so re-pinning replaces the note instead of stacking a new one on
every run. It is dropped for a value that has to be quoted: the parser
takes a quoted value verbatim, so a trailing comment would become part
of it. Newlines are folded to "; " for the same reason.
allow_secrets : bool, default False
Required to write a credential. A general-purpose file patcher must not
be the thing that puts a password into a file someone later commits, so
by default a name :func:_is_secret recognises is refused.
Returns¶
dict
{'updated': [...], 'added': [...], 'unchanged': [...]} of full
TDFS4DS_* names. Nothing is written when everything is unchanged.
Raises¶
ValueError path does not exist, a key is not a registered variable (it would only earn an "unknown .env variable" warning on load), or it is a credential without allow_secrets.
describe_config
¶
Show the configuration with secret VALUES hidden but their presence confirmed.
The counterpart to :func:export_config for the question you actually ask
when a deployment misbehaves: is this variable set? export_config
cannot answer it — it redacts a secret to a commented placeholder, which
reads identically whether the variable holds a password or nothing at all.
Never returns or prints a secret value. A secret reports its length
instead, which is enough to spot a truncated paste or a stray quote and not
enough to reconstruct. "Is this a credential?" is decided by
:func:_is_secret — the one authority for it — never re-derived here.
Parameters¶
source : {'env', 'module'}
'env' (default) reads the TDFS4DS_* environment variables,
so it reports what is set even when it never reached the module config
(the load-order trap: config.py populates tdfs4ds.<ATTR> once,
at import). 'module' snapshots the running configuration.
Pass-through variables have no module attribute and are always read
from the environment, whatever source says.
required : iterable of str, optional
Names to flag when missing, with or without the TDFS4DS_ prefix.
An unset variable is normally omitted to keep the report readable;
a required one is always shown, marked NOT SET (required).
display : bool, default True
Print the report. Set False to only receive the rows.
Returns¶
list of dict
One row per reported variable: name (with prefix), attr,
status ('set' / 'hidden' / 'unset'), value (the
real value, or None when hidden), secret, required and
length.
Examples¶
tdfs4ds.describe_config() # doctest: +SKIP tdfs4ds.describe_config(required=['TDFS4DS_TD_HOST']) # doctest: +SKIP rows = tdfs4ds.describe_config(display=False) # doctest: +SKIP
_print_config_rows
¶
Render :func:describe_config's rows. Plain ASCII, by convention.
A diagnostic must never be the thing that breaks: a legacy Windows console
raises UnicodeEncodeError on non-ASCII, so nothing here uses it.
load_config
¶
(Re-)load configuration from external sources.
Useful for pointing at non-default config files or refreshing values mid-session. Applies sources in priority order (lowest first):
- JSON config file (at path or auto-discovered)
.envfile (at dotenv_path or auto-discovered)- OS
TDFS4DS_*environment variables (always applied)
Parameters¶
path : str or pathlib.Path, optional
Explicit path to a JSON config file. Skips auto-discovery when given.
dotenv_path : str or pathlib.Path, optional
Explicit path to a .env file. Skips auto-discovery when given.
Examples¶
Auto-discover all sources::
import tdfs4ds
tdfs4ds.load_config()
Explicit paths::
tdfs4ds.load_config(
path='/project/configs/feature_store.json',
dotenv_path='/project/.env.local',
)
JSON config format (tdfs4ds.json)::
{
"schema": "MY_DATABASE",
"data_domain": "MY_PROJECT",
"display_logs": true,
"store_feature": "MERGE",
"varchar_size": 1024,
"instruct_model_provider": "openai",
"instruct_model_model": "gpt-4o"
}
Keys are case-insensitive. instruct_model_api_key is rejected from
JSON config — use a .env file or OS env var instead.
.env file format::
TDFS4DS_SCHEMA=MY_DATABASE
TDFS4DS_SCHEMA_VIEW=MY_VIEWS_DATABASE
TDFS4DS_DATA_DOMAIN=MY_PROJECT
TDFS4DS_INSTRUCT_MODEL_API_KEY=sk-...
Only TDFS4DS_* variables are read from the .env file.
Add .env to .gitignore to keep secrets out of source control.