Skip to content

feat: type what an object gives by attribute or item with a Members model - #159

Merged
SizzleUnrlsd merged 4 commits into
mainfrom
feat/member-types
Sep 25, 2026
Merged

SizzleUnrlsd merged 4 commits into
mainfrom
feat/member-types

Conversation

@SizzleUnrlsd

Copy link
Copy Markdown
Contributor

Summary

A Members(symbol, dynamic=None, defined=(), typed=()) model says what the attributes and items of a class's instances give. With it, every path to a pymongo collection denotes Collection, so one sink on Collection.find covers all of these:

  • client.shop.users.find;
  • client["shop"]["users"].find;
  • client.get_database("shop").get_collection("users").find;
  • a module-level db = client.shop;
  • a parameter annotated Collection;
  • an attribute inherited from the client class.

Closes #157. The pymongo models of CoreTrace-Entreprise/coretrace-python-analyzer-plugins#3 will use it.

Stacked on #156. Merge #156 first; this PR then shows only its own two commits.

Design

  • Where the model lives. Members is in semantic/symbols.py, next to the symbol resolution it drives. It is exported with the other models from coretrace_python.taint.
  • How it resolves an attribute.
    • typed wins;
    • defined keeps the class's own attributes on their path;
    • any other attribute, and every item, gives dynamic;
    • without dynamic, an item keeps its container's symbol, as before.
  • One place derives symbols. SymbolTable.attribute(symbol, name) and SymbolTable.item(symbol) are the only place where attributes and items derive symbols. That covers function bodies (derive_symbols), module-level names (_denoted), attribute chains lowered to one Symbol (ir/lowering.py), attributes inherited from an external base, and names resolved through resolve_expression.
  • How the engine provides it. The models reach the managers as the semantic.members input (MembersAnalysis). On its own it is empty, like interprocedural.clearing. The engine provides it wherever it provides the security models: single-file checks, project analyses and parallel workers.
  • Cache key. defined is normalised to a sorted tuple. repr(models) is part of the cache key, and a set's order changes between processes.

Changed expectation

test_transitive_dependencies_are_exposed now lists MembersAnalysis among the dependencies of SymbolAnalysis, because symbol resolution reads the models. The test still checks the transitive closure.

Tests

tests/test_members.py uses a fake docstore library, so the engine stays free of pymongo knowledge. It covers:

  • every access form: attribute, item, both mixed, getters, a sub-collection, a class with typed attributes only, a defined attribute, and a method called on what a member method returns;
  • module-level names, annotated parameters and inherited attributes;
  • one NOSQL sink on Collection.find, reached through every path;
  • the sorting of defined;
  • a plugin declaring the model in a project analysis, sequential and with jobs=2. A mutation check confirms that each of these two provisioning paths is needed.

Local results:

  • 1141 tests passed;
  • 19 regression snapshots passed, unchanged;
  • ruff check and mypy report nothing.

A module-level name denotes what its value denotes in a function body: an alias, an attribute, an item or a call of an import or of an earlier module-level name, resolved in statement order.
…odel

Symbol resolution reads the Members models the engine provides as the semantic.members input, so SymbolAnalysis now depends on MembersAnalysis besides scopes and imports.
@SizzleUnrlsd SizzleUnrlsd added the enhancement New feature or request label Sep 25, 2026
@SizzleUnrlsd SizzleUnrlsd self-assigned this Sep 25, 2026
@SizzleUnrlsd
SizzleUnrlsd merged commit 12fac51 into main Sep 25, 2026
10 checks passed
@SizzleUnrlsd
SizzleUnrlsd deleted the feat/member-types branch September 25, 2026 23:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Plugins: a Members model types what an object gives by attribute or item

1 participant