astral-sh / ruff

An extremely fast Python linter and code formatter, written in Rust.
https://docs.astral.sh/ruff
MIT License
30.7k stars 1.02k forks source link

Used submodule import flagged as unused in `except` handler #11448

Open bnomis opened 3 months ago

bnomis commented 3 months ago

Ruff version 0.4.4

Flags import some.module in the below as unused F401 but it is used

https://play.ruff.rs/f84ea9b2-0401-491f-a6a9-20f4e370d47f

import logging

import some.module  # ruff thinks this is not used

def func():
    logger = logging.getLogger('some')
    try:
        import some.other
        print(some.other.version)
        return None
    except Exception as e:
        logger.exception('exception' % e, extra={'now': some.module.now()})
        raise

If I move the import into the function - it's no longer flagged:

import logging

def func():
    import some.module  # now it's not flagged

    logger = logging.getLogger('some')
    try:
        import some.other
        print(some.other.version)
        return None
    except Exception as e:
        logger.exception('exception' % e, extra={'now': some.module.now()})
        raise
charliermarsh commented 3 months ago

This seems like a mix of some issues with modeling submodule imports (we roughly treat import some.module and import some.other as equivalent) and control flow analysis.

There's more on submodule imports in (e.g.) #4656.

charliermarsh commented 3 months ago

The interesting thing about submodule imports is -- this on its own will often:

def func():
    logger = logging.getLogger('some')
    try:
        import some.other
        print(some.other.version)
        return None
    except Exception as e:
        logger.exception('exception' % e, extra={'now': some.module.now()})
        raise