Features
Environment
The .env file, keeping secrets out of settings, Framework's environment variables, and scratch helpers
Overview
Framework keeps credentials and machine-specific values in a .env file that git ignores, and keeps them out of the settings files that git tracks. This guide covers the .env file, the environment variables Framework reads, and the helpers for quick, throwaway output.
The .env File
Every new project except a bare one has a .env file in its root. It starts with empty placeholders for a PostgreSQL connection and S3 storage.
POSTGRES_HOST=
POSTGRES_PORT=5432
POSTGRES_DB=
POSTGRES_SCHEMA=public
POSTGRES_USER=
POSTGRES_PASSWORD=
S3_BUCKET=
S3_ACCESS_KEY=
S3_SECRET_KEY=
S3_REGION=
S3_ENDPOINT=
S3_SESSION_TOKEN=
Fill in the values the project uses and add any others it needs.
scaffold() and settings_read() load .env into os.environ. Values in the file replace variables that are already set, as the R package's dotenv loader does, so a project behaves the same in both languages. The dotenv_location key in the settings points at a different file, or at a folder that holds one.
The file follows the rules of R's dotenv package.
- Blank lines and lines that start with
#are skipped. A#later in a line is part of the value. - Every other line is
KEY=VALUE, optionally preceded byexport. - A value wrapped in matching single or double quotes loses the quotes. Nothing inside the quotes is unescaped.
- A line that does not match this form is an error.
Keeping .env out of Git
Every project type's .gitignore excludes .env. Project creation and bootstrap() add a rule when the file is missing one, and creation stops with an error when git would still track .env. git_security_audit() fails when git tracks a .env file.
To tell collaborators which variables a project needs, commit a .env.example with empty values. bootstrap() copies it to .env in a fresh clone and lists the variables that are still empty.
Using Environment Variables in Settings
Settings refer to environment variables with env("VAR"), or env("VAR", "default") for a fallback.
connections:
databases:
warehouse:
driver: postgres
host: env("POSTGRES_HOST")
port: env("POSTGRES_PORT", "5432")
database: env("POSTGRES_DB")
user: env("POSTGRES_USER")
password: env("POSTGRES_PASSWORD")
The settings file can be committed and shared, and each person's credentials stay in their own .env. The settings.yml guide describes expressions.
Secrets Never Go in Settings
Framework refuses to store secret-looking values in settings. A variable counts as secret when its name contains PASSWORD, SECRET, TOKEN, ACCESS_KEY, API_KEY, PRIVATE_KEY, or CREDENTIAL.
- spec_check() rejects a project spec whose
envsection gives such a variable a value, so blueprints carry only empty placeholders. - configure_global() refuses such a value in
defaults.envof your global settings. - Framework Cloud project tokens are written to the project's
.env, and personal tokens to the system keyring.
import framework as fw
fw.configure_global({"defaults": {"env": {"DB_PASSWORD": "hunter2"}}})
SettingsError: defaults.env: secrets must not be stored in settings (DB_PASSWORD).
Leave the values empty and put them in each project's .env file.
When a secret has been committed by mistake, remove the file from git, commit, and rotate the secret, because it remains in the repository's history.
Environment Variables Framework Reads
| Variable | Effect |
|---|---|
FW_CONFIG_HOME |
The global config folder. See Setup. |
FW_CONFIG_ACTIVE |
The settings environment, such as production. R_CONFIG_ACTIVE and R_CONFIG_NAME are read after it. |
FW_SEED |
Turns on seeding in scaffold() when the settings do not decide. |
FW_CACHE_DIR |
The cache folder. See Caching. |
FW_LEDGER |
live, on, or true sends data hashes to the cloud ledger. off turns it off. |
FW_CLOUD_URL |
The Framework Cloud server. |
FW_CLOUD_TOKEN |
A personal cloud token, used before the keyring. |
FW_TOKEN_FILE |
A file that holds the personal cloud token. |
FW_PROJECT_TOKEN |
The project's cloud token, usually set in .env. |
S3_* and AWS_* |
Storage bucket credentials and locations. See Publishing. |
Scratch Files
The scratch folder holds throwaway output that does not belong in the project's results. Every project type's .gitignore excludes scratch/ folders. The folder is directories.scratch, which is scratch/ in standard and privacy-sensitive projects.
scratch_capture() writes an object to the scratch folder and returns it unchanged, so it can sit in the middle of a pipeline. DataFrames are written as TSV and other objects as text.
survey = fw.scratch_capture(fw.data_read("inputs.raw.survey"), "survey_peek", n=100)
fw.scratch_capture({"sites": ["north", "south"]}, "sites")
The arguments choose the output.
nameis the file name. An extension (.txt,.csv,.tsv, or.pkl) sets the format. Without a name, the file is namedcapture_<timestamp>.tois"text","csv","tsv", or"pickle".nwrites only the firstnrows of a DataFrame.locationwrites to another folder.
scratch_clean() deletes the files in the scratch folder and leaves its subfolders alone.
fw.scratch_clean()
Capturing Printed Output
capture_output() is a context manager that captures everything printed to standard output and standard error inside its block.
with fw.capture_output() as captured:
print(survey.describe())
captured.output
captured.lines
An exception inside the block is not caught. The output printed before it remains available in captured.output.