plesty init#

Initialize a new Plesty project from the official template. The project is created in the directory specified by the global --project-dir option (defaults to the current working directory), making the standard workflow as simple as:

mkdir plesty-my-device && cd plesty-my-device
plesty init device
plesty init [PROJECT_TYPE] [OPTIONS]

PROJECT_TYPE is one of device or experiment (default: default, not yet available).

Naming conventions#

All Plesty projects follow a consistent naming scheme derived from the module name (e.g. foo_bar):

Artifact

Convention

Example

Project folder

plesty-<kebab-name>

plesty-foo-bar

Source folder

plesty/<module_name>/

plesty/foo_bar/

PyPI distribution

plesty-<kebab-name>

plesty-foo-bar

Python import

plesty.<module_name>

plesty.foo_bar

The plesty- prefix in the folder name is automatically stripped when inferring the module name, so plesty-foo-barfoo_bar without needing --name.

Options#

Option

Default

Description

--name

inferred

Python module name — lowercase letters, digits, and _ only (e.g. foo_bar). Inferred from the directory name by stripping the plesty- prefix and converting hyphens to underscores.

--author

John Doe

Author name written into pyproject.toml and REUSE.toml

--email

john.doe@example.com

Author email written into pyproject.toml

--standard

quantum

Compliance standard for the generated CI pipeline: pixel, nebula, or quantum.

--no-ci

off

Skip generating .gitlab-ci.yml entirely.

Directory rules#

  • If --project-dir does not exist it is created automatically.

  • If it already exists it must be empty (hidden entries such as .git are ignored).

What init does#

After copying the template, plesty init automatically:

  1. Formats generated files — runs ruff format so the scaffold is already plesty check-clean from the first commit.

  2. Creates the initial git commit — required by versioningit to resolve a package version from git history.

  3. Installs the pre-push hook — writes .git/hooks/pre-push to run plesty check automatically before every git push (standard read from [tool.plesty] standard in pyproject.toml, default: quantum).

Examples#

# Minimal: module name inferred from directory, quantum CI, default author
mkdir plesty-power-meter && cd plesty-power-meter
plesty init device

# Explicit name and author
plesty --project-dir ~/projects/plesty-power-meter init device \
  --name power_meter \
  --author "Jane Doe" \
  --email jane@example.com

# Use nebula standard in CI (gates 1–6 only)
plesty --project-dir ~/projects/plesty-scan-exp init experiment \
  --name scan_exp \
  --standard nebula

# Skip CI file entirely
plesty --project-dir ~/projects/plesty-internal-tool init device \
  --name internal_tool \
  --no-ci

Generated project layout#

plesty-foo-bar/
├── plesty/
│   └── foo_bar/
│       ├── __init__.py
│       ├── __main__.py
│       ├── base_device.py       # device only
│       └── device.py            # device only
├── docs/
│   ├── index.md
│   └── toc.yaml
├── tests/
│   ├── __init__.py
│   └── test_foo_bar.py          # smoke tests covering all public methods
├── CHANGELOG.md
├── .env.example                # device only — connection credential template
├── .git/
│   └── hooks/
│       └── pre-push             # runs plesty check (standard from pyproject.toml)
├── .gitlab-ci.yml               # omitted when --no-ci
├── .gitignore                   # ignores .env (keeps .env.example tracked)
├── LICENSE                      # LGPL text, kept for forge (GitLab) detection
├── LICENSES/
│   └── LGPL-3.0-or-later.txt
├── REUSE.toml                   # declares copyright/license for every file
├── pyproject.toml
└── README.md

The pyproject.toml is pre-configured with:

  • The PyPI distribution name plesty-foo-bar (kebab-case)

  • packages = ["plesty"] so the module installs under the plesty namespace (import plesty.foo_bar)

  • Dynamic versioning via versioningit

  • plesty-lib as a runtime dependency

  • pytest, pytest-cov, mypy, and plesty-sdk under [dependency-groups] dev (included automatically by uv run — no --extra dev needed)

  • Sphinx docs settings under [tool.plesty.docs]

The generated .gitlab-ci.yml uses the unified plesty-standard-ci CI component from plesty-ci and passes access_token: $CI_BOT_TOKEN. Configure a project access token with read_repository + write_repository scopes and Maintainer role, then set it as a masked CI/CD variable named CI_BOT_TOKEN.

Use plesty update to change author info, the PyPI name, or CI standard after initialisation.

Device connection credentials (device only)#

Device projects are scaffolded to read their connection credentials from the environment rather than hard-coding them. The generated __main__.py loads three variables via plesty.lib.utils.EnvSettings:

Variable

Meaning

Required

DEVICE_HOST

Target device host / IP

yes

DEVICE_PORT

Target device port

yes

DEVICE_TCP_PORT

ZMQ port the device server binds (default 5555)

no

Resolution precedence per value is CLI argument > environment variable > default. The required DEVICE_HOST/DEVICE_PORT are validated with parser.error(...), so a missing credential produces a clean usage message instead of a traceback.

EnvSettings.load() reads ./.env and then the process environment (the process environment wins) and, by default, also registers the parsed .env values into os.environ. Rename these variables per device as needed — the names are just the scaffold defaults, not a fixed contract.

Workflow:

cp .env.example .env          # then fill in DEVICE_HOST / DEVICE_PORT
python -m plesty.foo_bar      # credentials read from .env
python -m plesty.foo_bar --host 10.0.0.5 --tcp-port 6000   # CLI overrides env

.env.example is committed as a template; the real .env is gitignored. The generated tests/test_foo_bar.py includes a skipif real-device test that consumes the same variables, so one .env drives both the server and the tests. It is skipped unless DEVICE_HOST is set.