Connecting a device needs a host, a port, sometimes a password — and none of that belongs in source. A new dependency-free EnvSettings loader (plesty.lib.utils.settings) reads connection and credential info from a .env file and the process environment, with a clean override > env > default precedence. Here's how to use it, and how to build a module on it.
You never touch code to connect. Create a .env file where you run the module and fill in the variables that module documents — for example:
# .env — keep it out of git; these values are placeholders
DEVICE_HOST=192.168.0.10
DEVICE_PORT=5025
DEVICE_PASSWORD=your-device-password
Start the device server and it reads those on load. A missing .env is fine when the values already live in your real environment (a CI secret, a shell export) — a real process variable always wins over the file, so the same module runs unchanged from your laptop to a lab server without an edit.
One .env covers the tests, too.
Because load() merges the file with the live environment, a device server and its test-suite read identical variables — tests just set DEVICE_* placeholders and stay isolated.
Writing a device module? Pull credentials through EnvSettings rather than hard-coding them or rolling your own loader. The whole pattern is four lines plus lookups:
from plesty.lib.utils.settings import EnvSettings
# seed from .env (if present) + the process env; also exports into os.environ
env = EnvSettings.load()
# required — raises KeyError naming the var if it is unset
password = env.require("DEVICE_PASSWORD")
# optional, typed, with a default
host = env.get("DEVICE_HOST", default="127.0.0.1")
port = env.get("DEVICE_PORT", default=5025, cast=int)
# a CLI argument, when given, wins over everything
host = env.get("DEVICE_HOST", default="127.0.0.1", override=args.host)
- Use
require()for anything that must never be hard-coded — it fails loudly, naming the missing variable, instead of connecting with a blank secret. - Use
get()with acast(int,float,bool—boolaccepts1/true/yes/on) for optional connection info. - Choose your own variable names and defaults —
EnvSettingsprescribes none — and document them so users know what to put in their.env.
Every lookup resolves through the same ladder — the first one that is set wins:
.envget() returns it; require() raises instead✗ before — secret in the code
client = Connect(
host="192.168.0.7",
password="hunter2", # committed 😱
)
✓ after — from the environment
env = EnvSettings.load()
client = Connect(
host=env.get("DEVICE_HOST"),
password=env.require("DEVICE_PASSWORD"),
)
Credentials and connection details live in the environment (.env); flexible operational tuning is configured separately (e.g. YAML). Because the helper is dependency-free and name-agnostic, every current and future module inherits the same discipline for free — the plesty-lib companion to the SDK-side credential scaffolding.