コンテンツにスキップ

module-variable-dependency

Category: Dependency Injection
Severity: Warning
Triggered by: pyscn analyze, pyscn check --select di

What it does

Flags a class that directly reads or writes a module-level mutable variable without a global statement — an implicit coupling to module state.

Why is this a problem?

Unlike a global assignment, reading a module-level name is silent: the class looks self-contained, but its behaviour actually depends on whatever lives in that module variable at call time. A test that instantiates the class in isolation may still pass or fail based on an unrelated import.

This also breaks substitutability. You can't give the class a different collaborator without monkey-patching the module, which is fragile and order-dependent. Two instances of the class are forced to share the same backing object whether you want that or not.

Making the collaborator a constructor parameter documents the dependency, allows per-instance configuration, and lets tests inject a fake without touching module globals.

Example

config = load_config()

class UserRepository:
    def find(self, user_id):
        conn = connect(config.database_url)
        return conn.query("SELECT * FROM users WHERE id = ?", user_id)

Use instead

Accept the collaborator as a constructor parameter.

class UserRepository:
    def __init__(self, database_url):
        self.database_url = database_url

    def find(self, user_id):
        conn = connect(self.database_url)
        return conn.query("SELECT * FROM users WHERE id = ?", user_id)

Options

Option Default Description
di.enabled false Must be true for analyze to run DI rules.
di.min_severity "warning" Raise to "error" to suppress this rule.

References