GithubHelp home page GithubHelp logo

codingjoe / relint Goto Github PK

View Code? Open in Web Editor NEW
55.0 5.0 12.0 66 KB

Write your own linting rules using regular expressions.

License: MIT License

Python 100.00%
regex linter lint qa qatools hacktoberfest

relint's Introduction

/(re)lint/

reLint

Regular Expression Linter

Write your own linting rules using regular expressions.

PyPi Version Test Coverage GitHub License

Installation

python3 -m pip install relint
# or, if you have super advanced linting expressions
python3 -m pip install "relint[regex]"

Usage

You can write your own regular rules in a YAML file, like so:

- name: No ToDo
  pattern: '(?i)todo' # case insensitive flag
  hint: Get it done right away!
  filePattern: .*\.(py|js)
  error: false

The name attribute is the name of your linter, the pattern can be any regular expression. The linter does lint entire files, therefore your expressions can match multiple lines and include newlines.

You can narrow down the file types your linter should be working with, by providing the optional filePattern attribute. The default is .*.

The optional error attribute allows you to only show a warning but not exit with a bad (non-zero) exit code. The default is true.

The following command will lint all files in the current directory:

relint -c .relint.yml FILE FILE2 ...

The default configuration file name is .relint.yml within your working directory, but you can provide any YAML or JSON file.

If you prefer linting changed files (cached on git) you can use the option --diff [-d] or --git-diff [-g]:

git diff --unified=0 | relint my_file.py --diff

pre-commit

You can automate the linting process by adding a pre-commit hook to your project. Add the following entry to your .pre-commit-config.yaml:

- repo: https://github.com/codingjoe/relint
  rev: 1.4.0
  hooks:
    - id: relint
      args: [-W]  # optional, if you want to fail on warnings during commit

relint's People

Contributors

amureki avatar anapaulagomes avatar codingjoe avatar dependabot[bot] avatar el-virus avatar janbednarik avatar moseb avatar tennox avatar tslmy avatar yangcht avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar

relint's Issues

Case insensitive flag?

Could you add support for case insensitive flag?
Even the example you provided is quite awkward:

- name: No ToDo
  pattern: '[tT][oO][dD][oO]'

maybe also just a flags field?

Add a negate flag

I would like to add a rule that fails when a regex is not matched, for example a VERSION file containing a v1.0.0 and a pattern like ^v (because a v prefix on a semver is not valid).

Crash on empty configuration

Traceback (most recent call last):
  File "/path/bin/relint", line 8, in <module>
    sys.exit(main())
  File "/path/lib/python3.8/site-packages/relint.py", line 220, in main
    tests = list(load_config(args.config))
  File "/path/lib/python3.8/site-packages/relint.py", line 60, in load_config
    for test in yaml.safe_load(fs):
TypeError: 'NoneType' object is not iterable

Reproduction:

  • create an empty file relint.yaml
  • run with relint -c relint.yaml

Globing or file tree walking is not working

OS: Windows
Python: 3.10

Setting up as described in the Readme leads to relint ** parsing absolutely no files.

  • glob.escape leads to glob.iglob returning with an empty set
  • a check verifying that path is a file is missing (add ... if os.path.isfile(path)
    i.e., modified main looks like this now
import os.path
# ...
    paths = {
        path
        for file in args.files
        for path in glob.iglob(file, recursive=True)
        if os.path.isfile(path)
    }
# ....

Still, when culprits are found, throws AttributeError: type object 'Syntax' has no attribute 'guess_lexer'
It looks like there has been a major change to rich, and this package is not locking a major version of it.

Add verbosity levels

In my usecase, I am defining rule with an extensive hint. While it might make sense to show it in majority of the cases, maybe sometimes in a known set of rules I just need to know which rule failed without the detailed description.
I could imagine it this way:

relint myfile.py

1>    myfile.py:12 relint rule name
2>    myfile.py:17 relint second rule name


~~~

relint myfile.py --verbose

1>    myfile.py:12 relint rule name
Hint: extensive rule description for multiple lines

2>    myfile.py:17 relint second rule name
Hint: another extensive rule description for multiple lines

Scan entire directory doesn't work

relint -c .relint.yml **

just returns:

relint: error: unrecognized arguments: <files and directories in my repo>

If I don't include the -c, I don't get this error, but I also don't see any output. It only works when I do

relint <path to specific file>

with a default config name

relint-pre-commit.sh ${@:1} needs to be "${@:1}" with quotes

In relint-pre-commit.sh the ${@:1} lacks quotes, i.e. it should be "${@:1}" to support arguments with spaces. Let me demo the difference to you:

$ demo_bad() { echo ${@:1} ; }

$ demo_good() { echo "${@:1}" ; }

$ demo_bad "one  two" "three  four"
one two three four

$ demo_good "one  two" "three  four"
one  two three  four

Officially publish a relint container image

Hi 👋

Would be nice to have an official container image of relint published somewhere: it really helps designing reusable pipelines when building blocks are containerized (VS install deps python, node and everyone’s favorite language runtime ;) )

Many thanks

support for non-fixed-width pattern look-behind

I noticed that the current default re package does not support non-fixed-width pattern look-behind.

And this feature is actually very useful and powerful to have. For example, the following is not supported by re but by regex.
(?<=\/\*(\*(?!\/)|[^*])*\*\/(\s|\S)*\n)(?!\/\*(\s|\S)*\n)(.{120,})(?!(\s(?!\/\*)|\S(?!\/\*))*\*\/\n)

Is it possible to switch the default re to the regex package, which supports such a feature? I have issued a PR for it.

Does not act on all files? (Despite lack of "filename: ..." and "exclude: ...")

I have a weird problem here that maybe you have an idea about.
I'm tryint to find uses of mock where it should be unittest.mock for Python, instead.
So I have:

$ cat .relint.yml 
- name: "PyPI mock instead of Python 3 unittest.mock"
  pattern: "^(import mock)"
  hint: "Please use unittest.mock of Python 3 rather than plain/PyPI mock."

$ cat .pre-commit-config.yaml 
repos:
  - repo: https://github.com/codingjoe/relint
    rev: 1.0.0
    hooks:
      - id: relint

For config. Now it gets interesting:

$ git grep -E '^(import mock)' '*.py' | wc -l
72

$ pre-commit run --all-files | fgrep .py | wc -l
4

$ git ls-files '*.py' | xargs relint | fgrep .py | wc -l
4

So why are only 4 out of those 74 matches found by relint — any ideas?

Semi-broken pre-commit hook configuration due to custom Git diff

Thanks a lot for fixing #70 regarding the file globbing support. As requested, I'm hereby opening up a new issue about the other somewhat related issue I noticed, specifically that the existing pre-commit hook in this repository is semi-broken.

The reason behind the incorrect behaviour is that

args: [--git-diff]
specifies the argument --git-diff, which triggers the git-diff logic as implemented by relint. This might work in some cases, but not in all of them.

As an example, if you run pre-commit run --all-files, relint will say that everything passed, but did not actually end up checking anything. While pre-commit will always pass a list of files to check to each configured linter, the pre-commit hook in this repository unfortunately adds its own logic on top of that with --git-diff. While relint will in fact scan all files as expected by pre-commit, the custom logic throws away all results, as there are no changes in the repository, resulting in relint always attesting that everything passes.

This can be easily fixed by simply removing the --git-diff argument from the .pre-commit-hooks.yaml. IMHO this is also the more correct approach, as pre-commit already decides which files to check, so I'd expect all linters to just lint the files they've actually been passed. Any additional custom logic on top is rather dangerous, as now the various linters no longer check the same set of files.

Could you please consider making this change and simply use the files passed by pre-commit as-is? I think the --git-diff helper is a legitimate and useful utility for standalone users, so I would definitely keep the feature around, but I think using it for pre-commit is not a good approach for the reasons outlined above. Thanks a lot in advance for looking into this!

Exclude specific files that would otherwise match a broader pattern

I work on a python repository and I'd like to use relint in pre-commit and CI pipeline to make sure nobody ever commits a print call, so I use this pattern specification:

- name: Leftover print
  pattern: "print\\("
  filename:
    - "*.py"

However, there is one file in the root of the repo - run.py which contains a few startup scripts and it uses prints to give some runtime info to the users.

Is there any way I can define the filename pattern in a way to include all .py files except run.py?

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.