Plugin surface check: from X import Y is recorded as X, so the surface is refused and allowances admit whole packages #606

Closed
opened 2026-10-01 10:48:20 +00:00 by tiagoagueda · 0 comments
Owner

Found on 2026-09-29 in a read-only review of postulo at 95348908d, running postulo.plugins.testing against a small package of import spellings.

Checked again on 2026-10-01 against main at 0a5cad587: still present.

imports_in records node.module for every from X import Y and never X.Y. Two things follow. from postulo.plugins import api, which is the spelling the core's own tests use, is reported as reaching past the surface, as postulo.plugins. And in the other direction an allowance is coarser than it reads: from postulo.core import site, models is recorded as postulo.core alone, so an entry allowing postulo.core "for site" lets every other module of postulo.core through unreported.

  • Where: plugins/testing.py:74-90 (imports_in: names = [module] for an ImportFrom); plugins/testing.py:107-114 (reaching_past_the_surface); the coarse allowances already in use at tests/test_plugin_surface.py:51-108 (REACHING_PAST: email, own_mail, smtp and postal_rules each allow postulo.core for one or two named modules).
  • What happens: checked on the snapshot: a package containing from postulo.plugins import api and from postulo import plugins gives reaching_past_the_surface(...) == ['postulo', 'postulo.plugins']. A second file with from postulo.core import site, models and from postulo.plugins import base, registry, checked with allowed={"postulo.core": "site"}, reports neither models nor base nor registry by name: only postulo.plugins, and nothing at all for models.
  • Why it matters: the check is published for plugin repositories (#229) and run by five of them (tests/test_surface.py in postulo-apprise, -dav, -helloworld, -imap and -paperless). An author who imports the surface the way the core's tests do gets a false failure; one who silences it by allowing postulo.plugins has allowed postulo.plugins.base, registry and installing too. The core's own REACHING_PAST entries document one module each and admit the whole package.
  • Fix: for an ImportFrom, record f"{module}.{alias.name}" for each imported name (keeping module itself only for import *), and treat a name as within an allowance when it equals the allowance or starts with it plus a dot. Then from postulo.plugins import api is SURFACE, from postulo.core import site is postulo.core.site, and the REACHING_PAST entries can name the module they mean (postulo.core.site, postulo.core.mail_auth, postulo.core.phones).

Done when

  • tests/test_plugin_surface.py has a test that from postulo.plugins import api passes assert_imports_only_the_surface, and one that from postulo.core import site, models with allowed={"postulo.core.site": "…"} reports postulo.core.models.
Found on 2026-09-29 in a read-only review of postulo at 95348908d, running `postulo.plugins.testing` against a small package of import spellings. Checked again on 2026-10-01 against `main` at `0a5cad587`: still present. `imports_in` records `node.module` for every `from X import Y` and never `X.Y`. Two things follow. `from postulo.plugins import api`, which is the spelling the core's own tests use, is reported as reaching past the surface, as `postulo.plugins`. And in the other direction an allowance is coarser than it reads: `from postulo.core import site, models` is recorded as `postulo.core` alone, so an entry allowing `postulo.core` "for `site`" lets every other module of `postulo.core` through unreported. - **Where:** `plugins/testing.py:74-90` (`imports_in`: `names = [module]` for an `ImportFrom`); `plugins/testing.py:107-114` (`reaching_past_the_surface`); the coarse allowances already in use at `tests/test_plugin_surface.py:51-108` (`REACHING_PAST`: `email`, `own_mail`, `smtp` and `postal_rules` each allow `postulo.core` for one or two named modules). - **What happens:** checked on the snapshot: a package containing `from postulo.plugins import api` and `from postulo import plugins` gives `reaching_past_the_surface(...) == ['postulo', 'postulo.plugins']`. A second file with `from postulo.core import site, models` and `from postulo.plugins import base, registry`, checked with `allowed={"postulo.core": "site"}`, reports neither `models` nor `base` nor `registry` by name: only `postulo.plugins`, and nothing at all for `models`. - **Why it matters:** the check is published for plugin repositories (#229) and run by five of them (`tests/test_surface.py` in postulo-apprise, -dav, -helloworld, -imap and -paperless). An author who imports the surface the way the core's tests do gets a false failure; one who silences it by allowing `postulo.plugins` has allowed `postulo.plugins.base`, `registry` and `installing` too. The core's own `REACHING_PAST` entries document one module each and admit the whole package. - **Fix:** for an `ImportFrom`, record `f"{module}.{alias.name}"` for each imported name (keeping `module` itself only for `import *`), and treat a name as within an allowance when it equals the allowance or starts with it plus a dot. Then `from postulo.plugins import api` is `SURFACE`, `from postulo.core import site` is `postulo.core.site`, and the `REACHING_PAST` entries can name the module they mean (`postulo.core.site`, `postulo.core.mail_auth`, `postulo.core.phones`). ## Done when - `tests/test_plugin_surface.py` has a test that `from postulo.plugins import api` passes `assert_imports_only_the_surface`, and one that `from postulo.core import site, models` with `allowed={"postulo.core.site": "…"}` reports `postulo.core.models`.
tiagoagueda added this to the 0.6.0 milestone 2026-10-01 10:48:20 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo#606
No description provided.