Skip to content

Setup

Get your development environment ready to build neops function blocks.

Prerequisites

You need three things installed:

Tool Version Purpose
Python 3.12+ Runtime for function blocks
uv latest Fast Python package manager
Code editor any VS Code or PyCharm recommended

Installing uv

curl -LsSf https://astral.sh/uv/install.sh | sh

See docs.astral.sh/uv for other installation methods.

Project Setup

Scaffold a new project with uv:

uv init my-neops-worker
cd my-neops-worker
uv add neops_worker_sdk
Prefer pip?

If you prefer pip over uv, create a virtual environment and install manually:

mkdir my-neops-worker && cd my-neops-worker
python -m venv .venv && source .venv/bin/activate
pip install neops_worker_sdk
pip install pytest pytest-asyncio  # for testing

Replace the generated pyproject.toml with a configuration tailored for neops development:

[project]
name = "my-neops-function-blocks"
version = "0.1.0"
description = "My first neops function blocks"
requires-python = ">=3.12"

dependencies = [
    "neops_worker_sdk",
]

[project.optional-dependencies]
test = [
    "pytest>=8.4.1",
    "pytest-asyncio>=1.1.0",
    "neops-remote-lab>=1.3.0",
]

[tool.ruff]
line-length = 120
target-version = "py312"

[tool.ruff.lint]
select = ["E", "F", "W", "I", "UP", "B"]

[tool.pytest.ini_options]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"

This gives you:

  • The neops_worker_sdk runtime dependency
  • Test dependencies (pytest, pytest-asyncio, neops-remote-lab) as optional extras
  • Sensible ruff and pytest configuration

Install everything, including test dependencies:

uv sync --all-extras

Tooling

Linting & Formatting — Ruff

We use Ruff for linting and formatting. It is a single, extremely fast tool (written in Rust) that replaces flake8, isort, and Black. The pyproject.toml above already includes a good baseline configuration.

Add Ruff as a development dependency so every contributor uses the same version:

uv add --dev ruff

Then run it from your project:

uv run ruff check .    # lint
uv run ruff format .   # format

Type Checking — Pyrefly

We use Pyrefly (by Meta) for type checking. It is a Rust-based type checker and language server that provides fast, accurate analysis for modern Python.

Add it as a development dependency:

uv add --dev pyrefly

Then run it:

uv run pyrefly check .
Why typed Python matters

neops function blocks rely heavily on type annotations. Here is why that matters:

  • Auto-completion — your editor understands parameter and return types
  • Early bug detection — type checkers catch mismatches before runtime
  • Schema generation — Pydantic models (used for parameters and results) derive JSON schemas from type hints automatically

Compare:

def run(params, device):
    ...

vs.

async def run(self, params: EchoParams, context: WorkflowContext) -> FunctionBlockResult[EchoResult]:
    ...

The typed version gives your editor, your tests, and the neops platform everything they need to validate your code before it ever touches a device.

IDE Recommendations

Recommended extensions:

Extension ID Purpose
Python ms-python.python Core Python support
Pyrefly meta.pyrefly Type checking, auto-completion, go-to-definition
Ruff charliermarsh.ruff Fast linting and formatting

Pyrefly acts as a full language server — it provides inline type errors, hover information, and code navigation out of the box. It replaces Pylance for type analysis, so you only need one of the two.

Recommended settings (.vscode/settings.json):

{
    "[python]": {
        "editor.defaultFormatter": "charliermarsh.ruff",
        "editor.formatOnSave": true
    }
}

Alternative: Pylance

If you prefer Microsoft’s Pylance (ms-python.vscode-pylance), it works well too — add "python.analysis.typeCheckingMode": "basic" to your settings. Pyrefly disables Pylance by default when both are installed; keep only one active to avoid duplicate diagnostics.

PyCharm has excellent built-in Python support — type checking, refactoring, and debugging work out of the box with fewer plugins.

Recommended plugins:

Plugin Purpose
Pydantic Enhanced support for Pydantic models (auto-completion, validation)

Configuration tips:

  • Ruff integration: Go to Settings > Tools > External Tools, add a new tool with program uv, arguments run ruff check $FilePath$, and working directory $ProjectFileDir$. Add a second entry with arguments run ruff format $FilePath$ for formatting. Assign keyboard shortcuts or configure file watchers to run on save.
  • Pyrefly for type checking: Add an external tool with program uv, arguments run pyrefly check $FilePath$, and working directory $ProjectFileDir$. This gives you the same type analysis as CI, beyond PyCharm’s built-in inspector.

Environment Configuration

neops workers discover the platform and function blocks through environment variables. Create a .env file in your project root:

URL_BLACKBOARD=https://your-neops-instance.example.com
DIR_FUNCTION_BLOCKS=./my_function_blocks
Variable Description
URL_BLACKBOARD URL of your neops instance’s blackboard API
DIR_FUNCTION_BLOCKS Directory where the worker discovers your function block modules

Tip

During local development with the test framework, these variables are not required – the test harness provides its own context.


Next: Write your first function block