Skip to content

Enforce Handbook tenet 2: using, never import #617

Description

@ocots

Context

The control-toolbox Handbook mandates, in tenet 2 of PHILOSOPHY.md (detailed in philosophy/modules.md#using-never-import):

Everything is qualified — with using, never import. Bring modules into scope, not their symbols (using Pkg: Pkg, using Pkg: Sub); call Module.symbol everywhere and extend methods qualified (Base.show(...)).

Two distinct violations to fix here:

  1. import anywhere — replace with using.
  2. The dotted submodule form using Pkg.Sub — it silently pulls Sub's exported names into scope too (unlike using Pkg: Sub), which the Handbook explicitly forbids.

Translation table (from philosophy/modules.md):

Instead of Write
import Pkg using Pkg: Pkg
import Pkg.Sub using Pkg: Sub
import Pkg.Sub: Sub using Pkg: Sub
import Pkg: sym1, sym2 using Pkg: sym1, sym2
using Pkg.Sub (forbidden) using Pkg: Sub

Scope — doc, code, and tests

  • Codesrc/, ext/, and any # Example docstring blocks.
  • Docsdocs/src/*.md (@example/@setup blocks) and any other .md showing Julia code (README, BREAKING.md/CHANGELOG.md migration snippets).
  • Tests — everything under test/, plus a regression-guard test (see below) so this can't silently regress again.

⚠️ Exception: a migration doc that quotes a past API verbatim in a "Before" snippet should be left as-is — that's a historical fact, not a style violation. Only fix "After"/current-usage examples.

Finding offending lines

# `import` statements, anywhere in Julia code or Markdown docs
rg --fixed-strings 'import ' -g '*.jl' -g '*.md' .

# forbidden dotted `using Pkg.Sub` form
rg -n 'using [A-Za-z][A-Za-z0-9]*\.[A-Za-z]' -g '*.jl' -g '*.md' .

Current count in this repo (rough — includes some CHANGELOG/BREAKING prose mentions that don't need changing; review each hit):

  • import: ~13
  • dotted using Pkg.Sub: 0

Smallest of the ecosystem repos for this cleanup — should be a quick, single PR.

Regression guard

CTLie already completed this migration (control-toolbox/CTLie.jl#24) and added a meta-test that scans every tracked .jl/.md file for both patterns:

test/suite/meta/test_no_import.jl

It's self-contained and auto-discovered by the standard CTBase.run_tests runner (suite/*/test_* glob) — copy/adapt it directly.

Note on sibling submodule imports

If this repo has a submodule manifest structure (src/<Name>/<Name>.jl), relative sibling imports like using ..Lower or using ..Core: AbstractTag are fine as-is and not part of this rule. Only the absolute dotted form (using Pkg.Sub, with a real package name, not ..) is forbidden.


🤖 Filed with Claude Code

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions