Coder Social home page Coder Social logo

best-doctor / mr_proper Goto Github PK

View Code? Open in Web Editor NEW
18.0 3.0 3.0 256 KB

Static Python code analyzer, that tries to check if functions in code are pure or not and why.

License: MIT License

Makefile 0.95% Python 99.05%
python pure-function static-analyzer

mr_proper's People

Contributors

arondit avatar dodgyturtle avatar edwardbetts avatar korneevm avatar kyleking avatar lgroux avatar mcproger avatar melevir avatar sutorei avatar vquadx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

mr_proper's Issues

Allow `_` usage

Now if function uses _ as var name, it considered not pure (it uses external name (_))

Repo is missing a LICENSE file

and so does the pypi release tarball.
It would be really nice to know the exact terms and conditions this library is licensed under.

But I assume that the MIT set in pypi meta data is correct for now

Missing `mypy_extensions` Upstream Dependency

Describe the bug

The upstream dependency mypy-extensions was removed in the commit - 613ff72

Usage of this dependency in code -

from mypy_extensions import TypedDict

To Reproduce

Steps to reproduce the behavior:

  1. Install flake8-functions==0.0.5
  2. Run it on any *.py file

Stack Trace

/usr/local/lib/python3.8/site-packages/flake8/plugins/manager.py:157: in load_plugin
    self._load()
/usr/local/lib/python3.8/site-packages/flake8/plugins/manager.py:134: in _load
    self._plugin = self.entry_point.load()
/usr/local/lib/python3.8/importlib/metadata.py:77: in load
    module = import_module(match.group('module'))
/usr/local/lib/python3.8/importlib/__init__.py:127: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
<frozen importlib._bootstrap>:1014: in _gcd_import
    ???
<frozen importlib._bootstrap>:991: in _find_and_load
    ???
<frozen importlib._bootstrap>:975: in _find_and_load_unlocked
    ???
<frozen importlib._bootstrap>:671: in _load_unlocked
    ???
<frozen importlib._bootstrap_external>:783: in exec_module
    ???
<frozen importlib._bootstrap>:219: in _call_with_frames_removed
    ???
/usr/local/lib/python3.8/site-packages/flake8_functions/checker.py:6: in <module>
    from flake8_functions.function_purity import check_purity_of_functions
/usr/local/lib/python3.8/site-packages/flake8_functions/function_purity.py:5: in <module>
    from mr_proper.public_api import is_function_pure
/usr/local/lib/python3.8/site-packages/mr_proper/public_api.py:13: in <module>
    from mr_proper.utils.ast_pure import get_not_pure_internal_calls
/usr/local/lib/python3.8/site-packages/mr_proper/utils/ast_pure.py:6: in <module>
    from mypy_extensions import TypedDict
E   ModuleNotFoundError: No module named 'mypy_extensions'

During handling of the above exception, another exception occurred:
/usr/local/lib/python3.8/site-packages/pluggy/hooks.py:286: in __call__
    return self._hookexec(self, self.get_hookimpls(), kwargs)
/usr/local/lib/python3.8/site-packages/pluggy/manager.py:93: in _hookexec
    return self._inner_hookexec(hook, methods, kwargs)
/usr/local/lib/python3.8/site-packages/pluggy/manager.py:84: in <lambda>
    self._inner_hookexec = lambda hook, methods, kwargs: hook.multicall(
/usr/local/lib/python3.8/site-packages/_pytest/runner.py:171: in pytest_runtest_call
    raise e
/usr/local/lib/python3.8/site-packages/_pytest/runner.py:163: in pytest_runtest_call
    item.runtest()
/usr/local/lib/python3.8/site-packages/pytest_flake8.py:120: in runtest
    found_errors, out, err = call(
/usr/local/lib/python3.8/site-packages/py/_io/capture.py:150: in call
    res = func(*args, **kwargs)
/usr/local/lib/python3.8/site-packages/pytest_flake8.py:203: in check_file
    app.find_plugins(config_finder)
/usr/local/lib/python3.8/site-packages/flake8/main/application.py:159: in find_plugins
    self.check_plugins.load_plugins()
/usr/local/lib/python3.8/site-packages/flake8/plugins/manager.py:415: in load_plugins
    plugins = list(self.manager.map(load_plugin))
/usr/local/lib/python3.8/site-packages/flake8/plugins/manager.py:302: in map
    yield func(self.plugins[name], *args, **kwargs)
/usr/local/lib/python3.8/site-packages/flake8/plugins/manager.py:413: in load_plugin
    return plugin.load_plugin()
/usr/local/lib/python3.8/site-packages/flake8/plugins/manager.py:164: in load_plugin
    raise failed_to_load
E   flake8.exceptions.FailedToLoadPlugin: Flake8 failed to load plugin "CFQ" due to No module named 'mypy_extensions'.

Add directory processing, not per file

Now mr_proper accepts filename argument and checks only one file. We should specify directory_or_filename parameter.

If directory is specified, all files in the dir should be checked.

Manually check mr_proper on 200+ python repos

To be sure, that mr_proper handles most of widely used code cases in not breaks, we should write
a script, that:

  • Downloads 200+ python repos from Github.
  • Runs mr_proper on all of them.
  • Checks that mr_proper not breaks with exception.

Incorrect Package Description

Hi, I ran into issue #13 and while tracing the error, I was temporarily confused by the package description in the lock file until I read the full README. I think you might want to change the description to Static Python code analyzer that tries to check if functions in code are pure or not and why.

description='Package to find typos in russian text.',

(The description is also shown on PyPi: https://pypi.org/project/mr-proper/#history)

functions using context managers wrongly detected as not pure

Describe the bug
Variables assigned from contextmanager are not detected as local variables.

To Reproduce
run

from contextlib import contextmanager
from mr_proper.main import check_file


@contextmanager
def foo():
    yield "foobar"


def main():
    with foo() as f:
        return f


if __name__ == "__main__":
    check_file(__file__, recursive=True)

This gives the ouput

foo is pure!
main is not pure because of:
        it uses external name (f)

Expected behavior
main should be detected a pure

Config of the maximum number of function arguments

How about limiting the number of arguments to a function? When a function seems to need more than two or three arguments, it is likely that some of those arguments ought to be wrapped into a function of their own. This will help to avoid situations with large function signatures and will certainly increase readability, as well as separation of logic.

Add --exit-zero kwarg

If mr_proper finds not pure function, it should exit with non-zero code. If --exit-zero is specified, it should always exit with zero code.

Add config option for `uses_only_args_and_local_vars/allow_external_class_usage`

Is your feature request related to a problem? Please describe.

I get these errors on my "pure" functions:

_combine is not pure because of:
	it uses external name (entries)
	it uses external name (Language)
	it uses external name (phrase)
	it uses external name (defn)
	it uses external name (lang)
	it uses external name (Definition)

IMO, these are false positives. It looks like setting allow_external_class_usage to True would resolve some of these. (?) The option was coded, but not accessible from the CLI.

Some, though, seem to be an inability to understand Python 3.10 match and type hints:

def _combine(*entries: Iterable[Entry]) -> Iterable[Entry]:
    """Combine single-entry terms with the same phrase."""

    all_entries = cast(Iterable[Entry], concat(entries))

    term_dict: dict[tuple[str, Language], list[Definition]] = defaultdict(list)

    for entry in sorted(all_entries):
        match(entry.definitions):
            case [defn]:
                key = (entry.phrase, entry.language)
                term_dict[key].append(defn)
            case _:
                raise ValueError(f"Entry expected to have exactly one definition: {entry}")

    for (phrase, lang), defns in term_dict.items():
        yield Entry(phrase, defns, lang)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.