Skip to content

module-import-not-at-top-of-file (E402) - missing support for site.addsitedir() #16247

@Sarcasm

Description

@Sarcasm

Description

Failing file ruff-E402-addsitedir.py:

#!/usr/bin/env python

import os
import site
import sys
import sysconfig

site.addsitedir(
    os.path.join(
        os.path.dirname(os.path.dirname(__file__)),
        sysconfig.get_path("purelib", vars={"base": "."}),
    )
)

from mypkg.__main__ import main

if __name__ == "__main__":
    sys.argv[0] = sys.argv[0].removesuffix(".py")
    sys.exit(main())

Ruff check complains:

$ ruff check --select E402 ruff-E402-addsitedir.py
ruff-E402-addsitedir.py:15:1: E402 Module level import not at top of file
   |
13 | )
14 | 
15 | from mypkg.__main__ import main
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E402
16 | 
17 | if __name__ == "__main__":
   |

Found 1 error.

Looking at the code, sys.path and some others cases are handled

https://github.com/astral-sh/ruff/blob/0.9.6/crates/ruff_linter/src/checkers/ast/mod.rs#L552-L562

if !(self.semantic.seen_import_boundary()
|| stmt.is_ipy_escape_command_stmt()
|| helpers::is_assignment_to_a_dunder(stmt)
|| helpers::in_nested_block(self.semantic.current_statements())
|| imports::is_matplotlib_activation(stmt, self.semantic())
|| imports::is_sys_path_modification(stmt, self.semantic())
|| imports::is_os_environ_modification(stmt, self.semantic())
|| imports::is_pytest_importorskip(stmt, self.semantic()))
{
self.semantic.flags |= SemanticModelFlags::IMPORT_BOUNDARY;
}

but site.addsitedir seems missing, although it appends to sys.path internally:

https://github.com/python/cpython/blob/3.13/Lib/site.py#L238

BTW, thanks for Ruff, it's a great piece of software!

Metadata

Metadata

Assignees

Labels

help wantedContributions especially welcomeruleImplementing or modifying a lint rule

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions