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.

✨ feat plesty-lib lib#11 · 35d4102 + 5839536
Using plestyPoint a device at your credentials

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.

ContributingRead credentials in your module

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)
The precedence, when a value could come from several places

Every lookup resolves through the same ladder — the first one that is set wins:

1 · highest
override
an explicit value, e.g. a parsed CLI argument — returned as-is
2
env var
from the process environment or the seeded .env
3 · fallback
default
get() returns it; require() raises instead
The line it draws

✗ 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.