hchasestevens / bellybutton Goto Github PK
View Code? Open in Web Editor NEWCustom Python linting through AST expressions
License: MIT License
Custom Python linting through AST expressions
License: MIT License
In my usage of this awesome tool I found out, that # bb: disable
can sometimes hide other errors, which would be otherwise addressed. Let's consider following example:
deprecated_fn(42 + inner_fn())
So one day, first function became deprecated and thus rule DeprecatedFnCall was created. For some reason a programmer decided, that he still needs to keep that old deprecated function and so he disabled the warning.
deprecated_fn(42 + inner_fn()) # bb: disable
But the other day, inner_fn
became deprecated too and I think you can see the problem now. If he'd been allowed to do something similar to what pylint does:
deprecated_fn(42 + inner_fn()) # bb: disable = DeprecatedFnCall
With the creation of the new rule, he would be able to detect this fatal problem, because it would immediately show up as an error.
Of course, this is you project and this is only a suggestion :)
I am also willing to create this feature myself, if you like this idea and don't {want | have time} to deal with it.
Hi,
I need a rule that fails the lint when it detects a return statement within a try/catch block. How can this be done?
Python 3.7 removes re._pattern_type, can use re.Pattern instead.
See another projects issue: beetbox/beets#2986
I am creating a tool for code quality checks, which uses pylint and mypy and I want to be able to integrate bellybutton to it. Problem is, that the tool isn't alway run from root directory of the project and so the default configuration file ins't always where it needs to be.
This would be easily solved by command line option specifying the configuration file location.
I can easily implement this myself, if you don't {want|have time} to do so.
Can we use this library programmatically inside through python file? if yes kindly give an example
Hi, pyyaml was updated yesterday https://pypi.org/project/PyYAML/#history and now it is failing bellybutton lint
.
Steps to reproduce:
pip install bellybutton
bellybutton init
bellybutton lint
produces/home/artmis/.virtualenvs/marv-backend/lib/python3.7/site-packages/bellybutton/parsing.py:176: YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details.
loaded = yaml.load(fileobj)
Traceback (most recent call last):
File "/home/artmis/.virtualenvs/marv-backend/bin/bellybutton", line 10, in <module>
sys.exit(main())
File "/home/artmis/.virtualenvs/marv-backend/lib/python3.7/site-packages/bellybutton/cli.py", line 218, in main
for arg in args.func.__code__.co_varnames[:args.func.__code__.co_argcount]
File "/home/artmis/.virtualenvs/marv-backend/lib/python3.7/site-packages/bellybutton/cli.py", line 163, in lint
rules = load_config(f)
File "/home/artmis/.virtualenvs/marv-backend/lib/python3.7/site-packages/bellybutton/parsing.py", line 176, in load_config
loaded = yaml.load(fileobj)
File "/home/artmis/.virtualenvs/marv-backend/lib/python3.7/site-packages/yaml/__init__.py", line 114, in load
return loader.get_single_data()
File "/home/artmis/.virtualenvs/marv-backend/lib/python3.7/site-packages/yaml/constructor.py", line 43, in get_single_data
return self.construct_document(node)
File "/home/artmis/.virtualenvs/marv-backend/lib/python3.7/site-packages/yaml/constructor.py", line 52, in construct_document
for dummy in generator:
File "/home/artmis/.virtualenvs/marv-backend/lib/python3.7/site-packages/yaml/constructor.py", line 404, in construct_yaml_map
value = self.construct_mapping(node)
File "/home/artmis/.virtualenvs/marv-backend/lib/python3.7/site-packages/yaml/constructor.py", line 210, in construct_mapping
return super().construct_mapping(node, deep=deep)
File "/home/artmis/.virtualenvs/marv-backend/lib/python3.7/site-packages/yaml/constructor.py", line 135, in construct_mapping
value = self.construct_object(value_node, deep=deep)
File "/home/artmis/.virtualenvs/marv-backend/lib/python3.7/site-packages/yaml/constructor.py", line 92, in construct_object
data = constructor(self, node)
File "/home/artmis/.virtualenvs/marv-backend/lib/python3.7/site-packages/yaml/constructor.py", line 420, in construct_undefined
node.start_mark)
yaml.constructor.ConstructorError: could not determine a constructor for the tag '!settings'
in "/home/artmis/wood/marv-backend/.bellybutton.yml", line 2, column 14
Versions:
bellybutton==0.2.4
PyYAML==5.1
When I use PyYAML==3.13
everything works correctly. A quick solution would be to limit the version in setup.py
to PyYAML>=3.12,<4.0
, but it would be better to fix the actual problem in the long term.
Bellybutton doesn't like this:
filter_by:
description: Use SQLAlchemy's filter_by for concision
# Find calls to "filter" that:
#
# - are chained after a call to "query" with one argument,
# - have one argument,
# - which is an equality comparison
# * which has a LHS which is an attribute access on a name
expr: >
//Call[ ./func/Attribute[ @attr='filter'
and ./value/Call[./func/Attribute[@attr='query']
and ./args[count(child::*) = 1]]
]
and ./args[count(child::*) = 1]
and ./args/Compare[ ./ops/Eq
and ./left/Attribute[ @attr != 'attributes'
and ./value/Name
]
]
]
example: |
session.query(Model).filter(Model.attr == baz)
instead: |
session.query(Model).filter_by(attr = baz)
settings: *all_files
it says:
ERROR: /x/frontend/.bellybutton.yml, rule `filter_by`: 'str' object has no attribute 'match'
It works fine if you inline expr
, but this is a pain because expr
is huge:
expr: //Call[./func/Attribute[ @attr='filter' and ./value/Call[./func/Attribute[@attr='query'] and ./args[count(child::*) = 1]]] and ./args[count(child::*) = 1] and ./args/Compare[ ./ops/Eq and ./left/Attribute[ @attr != 'attributes' and ./value/Name]]]
This is version 0.3.0.
Noticed that when specifying the --modified-only flag, bellybutton no longer filters for only '.py' files, which causes it to try and parse unwanted files.
While having an option to specify these files using configuration file is cool, in my use case, it is not the best.
I am creating a tool for code quality checks, which uses pylint and mypy and I want to be able to integrate bellybutton to it. Unfortunately bellybutton doesn't allow to specify, on which files it should run using command line. This turns out to be very limiting, because my tool could be launched on specified files only.
I think, it would be better, if user could specify the files using command line, not only using the configuration file.
I am willing to implement this myself, if you don't {want|have time} to do it yourself, if you like it.
Traceback:
Traceback (most recent call last):
File "/usr/local/bin/bellybutton", line 10, in <module>
sys.exit(main())
File "/usr/local/lib/python3.6/dist-packages/bellybutton/cli.py", line 218, in main
for arg in args.func.__code__.co_varnames[:args.func.__code__.co_argcount]
File "/usr/local/lib/python3.6/dist-packages/bellybutton/cli.py", line 191, in lint
for failure in linting_failures(filepaths, rules):
File "/usr/local/lib/python3.6/dist-packages/bellybutton/cli.py", line 134, in linting_failures
for filepath, file_contents in files:
File "/usr/local/lib/python3.6/dist-packages/bellybutton/cli.py", line 109, in open_python_files
contents = f.read()
File "/usr/lib/python3.6/encodings/ascii.py", line 26, in decode
return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe3 in position 3487: ordinal not in range(128)
Hi
One of your dependencies astpath
upgraded on Friday and removed an argument return_lines
from find_in_ast
function call.
The lines concerned are https://github.com/hchasestevens/bellybutton/blob/master/bellybutton/linting.py#L57
and
https://github.com/hchasestevens/bellybutton/blob/master/bellybutton/parsing.py#L137
a simple fix would be to fix the version of astpath until a full change can be made.
Thanks
I created a simple rule from which I expected to fail on every single file in my project:
settings:
all_files: &all_files !settings
included:
- ~+/*
excluded:
- ~+/.tox/*
allow_ignore: yes
default_settings: *all_files
rules:
SimpleRule:
description: "Simple rule"
expr: !regex .*
And then I launched it:
bellybutton lint
Which results in a crash:
Traceback (most recent call last):
File "/home/dev_intern/.virtualenvs/bellybutton-test/bin/bellybutton", line 11, in <module>
sys.exit(main())
File "/home/dev_intern/.virtualenvs/bellybutton-test/lib/python3.5/site-packages/bellybutton/cli.py", line 203, in main
for arg in args.func.__code__.co_varnames[:args.func.__code__.co_argcount]
File "/home/dev_intern/.virtualenvs/bellybutton-test/lib/python3.5/site-packages/bellybutton/cli.py", line 167, in lint
linting_results = list(lint_file(filepath, file_contents, rules))
File "/home/dev_intern/.virtualenvs/bellybutton-test/lib/python3.5/site-packages/bellybutton/linting.py", line 65, in lint_file
for match in re.finditer(rule.expr)
TypeError: finditer() missing 1 required positional argument: 'string'
Can this be fixed soon?
Hi,
I would love to be able to explicitly tell bellybutton which configuration file to use.
Furthermore, I believe it might be sensible to allow for multiple configuration files to be loaded, which might help to apply the same rules over multiple projects w/o config duplication.
bellybutton lint --config /some/path/shared_bellybutton.yml .bellybutton.yml
This could simply mean to have the rules from the files concatenated or result with rules in .bellybutton.yml
overwriting rules with the same names in /some/path/shared_bellybutton.yml
.
What do you think?
I have a project where I put lots of virtual environments under .mam
. I've generated a config using bellybutton init
and then excluded that directory with the following settings file:
settings:
all_files: &all_files !settings
included:
- ~+/*
excluded:
- ~+/.tox/*
- ~+/.mam/*
allow_ignore: yes
default_settings: *all_files
rules:
ExampleRule:
description: "Empty module."
expr: /Module/body[not(./*)]
example: ""
instead: |
"""This module has a docstring."""
I get the error in #22 from these files. I know this because I changed cli#109 to use a try except and raise the file name as a new error. The problem file is:
.\.mam\bandit\Lib\functools.py
I'm guessing I'm doing something wrong. But it's not excluding the file.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.