STANDARDS.md binds every repository in the NAPALM org: one default branch, Conventional Commits, the device-types contract, test-driven development, clean-code limits, a quality ratchet for existing code, packaging rules and releases by tag to PyPI. napalm-standard holds what a tool can check: the conformance check (with release rules on a tag), the quality ratchet (ported from netOrk's quality_ratchet.py), and the Gitea release from the CHANGELOG section. .gitea/workflows/driver.yml is the CI every driver calls; template/ is a new driver's starting point and passes the check as it is.
89 lines
2.1 KiB
Python
89 lines
2.1 KiB
Python
"""A driver repository on disk that meets the standard, to break one rule at a time."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pathlib
|
|
import textwrap
|
|
from collections.abc import Callable
|
|
|
|
import pytest
|
|
|
|
PYPROJECT = """\
|
|
[build-system]
|
|
requires = ["setuptools>=68"]
|
|
build-backend = "setuptools.build_meta"
|
|
|
|
[project]
|
|
name = "napalm-example"
|
|
version = "1.2.0"
|
|
description = "NAPALM driver for Example devices"
|
|
readme = "README.md"
|
|
license = "Apache-2.0"
|
|
requires-python = ">=3.10"
|
|
dependencies = [
|
|
"napalm>=5.0",
|
|
"napalm-device-types>=4.21",
|
|
]
|
|
|
|
[project.urls]
|
|
Repository = "https://git.netork.io/NAPALM/napalm-example"
|
|
Issues = "https://git.netork.io/NAPALM/napalm-example/issues"
|
|
|
|
[project.entry-points."napalm.drivers"]
|
|
example = "napalm_example:ExampleDriver"
|
|
|
|
[tool.mypy]
|
|
strict = true
|
|
|
|
[tool.coverage.run]
|
|
source = ["napalm_example"]
|
|
|
|
[tool.coverage.report]
|
|
fail_under = 80
|
|
"""
|
|
|
|
CHANGELOG = """\
|
|
# Changelog
|
|
|
|
## [Unreleased]
|
|
|
|
## [1.2.0] - 2026-10-22
|
|
|
|
### Added
|
|
- Interfaces.
|
|
|
|
## [1.1.0] - 2026-10-01
|
|
|
|
### Fixed
|
|
- Facts.
|
|
"""
|
|
|
|
RepoFactory = Callable[..., pathlib.Path]
|
|
|
|
|
|
@pytest.fixture
|
|
def make_repo(tmp_path: pathlib.Path) -> RepoFactory:
|
|
"""Write a conforming repo; ``files`` overrides or (with None) removes a path."""
|
|
|
|
def make(files: dict[str, str | None] | None = None) -> pathlib.Path:
|
|
layout: dict[str, str | None] = {
|
|
"pyproject.toml": PYPROJECT,
|
|
"README.md": "# napalm-example\n\nA driver.\n",
|
|
"CHANGELOG.md": CHANGELOG,
|
|
"LICENSE": "Apache License\nVersion 2.0, January 2004\n",
|
|
"napalm_example/__init__.py": "",
|
|
"napalm_example/py.typed": "",
|
|
".gitea/workflows/ci.yml": "name: CI\n",
|
|
"tests/test_driver.py": "def test_nothing():\n pass\n",
|
|
}
|
|
layout.update(files or {})
|
|
for rel, content in layout.items():
|
|
if content is None:
|
|
continue
|
|
path = tmp_path / rel
|
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
path.write_text(textwrap.dedent(content))
|
|
return tmp_path
|
|
|
|
return make
|