From 51509db2d0fbcd12e26f8ece3e8f2576b229fcfd Mon Sep 17 00:00:00 2001 From: Chentao Yang Date: Fri, 2 Aug 2024 00:22:25 +0200 Subject: [PATCH 01/17] Update COOKBOOK.md Adding a regex example to find line-length issues of any non-comment part of the code. --- COOKBOOK.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/COOKBOOK.md b/COOKBOOK.md index c1a6a36..0b87661 100644 --- a/COOKBOOK.md +++ b/COOKBOOK.md @@ -7,6 +7,7 @@ A collection of recipes for reLint. Please feel free to contribute! - [Python](#python) - [Django](#django) - [HTML](#html) +- [C/C++](#cc) # Python @@ -104,3 +105,13 @@ A collection of recipes for reLint. Please feel free to contribute! You may use a CSS class instead. filePattern: .*\.(html|vue|jsx|tsx) ``` + +# C/C++ + +```yaml +- name: no line longer than 80 characters in a line (excluding comments) # by @yangcht + pattern: '(?<=\/\*(\*(?!\/)|[^*])*\*\/(\s|\S)*\n)(?!\/\*(\s|\S)*\n)(.{120,})(?!(\s(?!\/\*)|\S(?!\/\*))*\*\/\n)' + hint: | + Please do not use more than 80 characters in codes except for comments. + filePattern: .*\.(C|cc|cxx|cpp|c++|cppm) +``` From 4f836fc8fdded8010c29ccf5f72700a1589737fe Mon Sep 17 00:00:00 2001 From: Chentao Yang Date: Fri, 2 Aug 2024 00:28:28 +0200 Subject: [PATCH 02/17] Update COOKBOOK.md Fix typo. --- COOKBOOK.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/COOKBOOK.md b/COOKBOOK.md index 0b87661..3c0870c 100644 --- a/COOKBOOK.md +++ b/COOKBOOK.md @@ -109,9 +109,9 @@ A collection of recipes for reLint. Please feel free to contribute! # C/C++ ```yaml -- name: no line longer than 80 characters in a line (excluding comments) # by @yangcht - pattern: '(?<=\/\*(\*(?!\/)|[^*])*\*\/(\s|\S)*\n)(?!\/\*(\s|\S)*\n)(.{120,})(?!(\s(?!\/\*)|\S(?!\/\*))*\*\/\n)' +- name: no line longer than 120 characters in a line (excluding comments) # by @yangcht + pattern: '(? Date: Fri, 2 Aug 2024 10:13:10 +0200 Subject: [PATCH 03/17] Update config.py upgrade from re to regex to support more features. --- relint/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relint/config.py b/relint/config.py index 38be530..9177af6 100644 --- a/relint/config.py +++ b/relint/config.py @@ -1,5 +1,5 @@ import collections -import re +import regex as re import warnings import yaml From a2470e49941998b261ec08e34793a03680670081 Mon Sep 17 00:00:00 2001 From: Chentao Yang Date: Fri, 2 Aug 2024 10:14:16 +0200 Subject: [PATCH 04/17] Update parse.py upgrade to regex from re --- relint/parse.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relint/parse.py b/relint/parse.py index 07138a6..dbee513 100644 --- a/relint/parse.py +++ b/relint/parse.py @@ -1,7 +1,7 @@ from __future__ import annotations import collections -import re +import regex as re from rich import print as rprint from rich.console import Group From 50b63a2cc809aa3f5bd9552a1f61b2f087a44795 Mon Sep 17 00:00:00 2001 From: Chentao Yang Date: Fri, 2 Aug 2024 10:14:45 +0200 Subject: [PATCH 05/17] Update linter-requirements.txt --- linter-requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/linter-requirements.txt b/linter-requirements.txt index 4b8d76c..868c714 100644 --- a/linter-requirements.txt +++ b/linter-requirements.txt @@ -3,3 +3,4 @@ black==24.4.2 flake8==7.1.0 isort==5.13.2 pydocstyle[toml]==6.3.0 +regex From f6a0b748e5770af27370204725f1df512fe8df23 Mon Sep 17 00:00:00 2001 From: Chentao Yang Date: Fri, 2 Aug 2024 10:25:31 +0200 Subject: [PATCH 06/17] Update COOKBOOK.md Fixing unicode issues --- COOKBOOK.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/COOKBOOK.md b/COOKBOOK.md index 3c0870c..c1e622c 100644 --- a/COOKBOOK.md +++ b/COOKBOOK.md @@ -110,7 +110,7 @@ A collection of recipes for reLint. Please feel free to contribute! ```yaml - name: no line longer than 120 characters in a line (excluding comments) # by @yangcht - pattern: '(? Date: Wed, 7 Aug 2024 22:15:44 +0200 Subject: [PATCH 07/17] revert doc changes --- COOKBOOK.md | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/COOKBOOK.md b/COOKBOOK.md index c1e622c..c1a6a36 100644 --- a/COOKBOOK.md +++ b/COOKBOOK.md @@ -7,7 +7,6 @@ A collection of recipes for reLint. Please feel free to contribute! - [Python](#python) - [Django](#django) - [HTML](#html) -- [C/C++](#cc) # Python @@ -105,13 +104,3 @@ A collection of recipes for reLint. Please feel free to contribute! You may use a CSS class instead. filePattern: .*\.(html|vue|jsx|tsx) ``` - -# C/C++ - -```yaml -- name: no line longer than 120 characters in a line (excluding comments) # by @yangcht - pattern: '(? Date: Wed, 7 Aug 2024 23:11:13 +0200 Subject: [PATCH 08/17] Adding regex in a try block --- linter-requirements.txt | 1 - pyproject.toml | 1 + relint/config.py | 23 ++++++++++++++++++++--- relint/parse.py | 24 +++++++++++++++++++----- 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/linter-requirements.txt b/linter-requirements.txt index 6a5ab4b..459cdbb 100644 --- a/linter-requirements.txt +++ b/linter-requirements.txt @@ -3,4 +3,3 @@ black==24.8.0 flake8==7.1.1 isort==5.13.2 pydocstyle[toml]==6.3.0 -regex diff --git a/pyproject.toml b/pyproject.toml index d665334..39f026b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,6 +35,7 @@ test = [ "pytest-cov", "pytest-mock", ] +extra = ["regex"] [project.scripts] relint = "relint.__main__:main" diff --git a/relint/config.py b/relint/config.py index 9177af6..61ae487 100644 --- a/relint/config.py +++ b/relint/config.py @@ -1,5 +1,4 @@ import collections -import regex as re import warnings import yaml @@ -17,6 +16,24 @@ ), ) +try: + import re + re_compile = re.compile +except ImportError: + re_compile = None + +def compile_pattern(pattern): + try: + return re_compile(pattern, re.MULTILINE) + except (re.error, AttributeError) as e: + try: + import regex + except ImportError: + import subprocess + import sys + subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'regex']) + import regex + return regex.compile(pattern, regex.MULTILINE) def load_config(path, fail_warnings, ignore_warnings): with open(path) as fs: @@ -26,10 +43,10 @@ def load_config(path, fail_warnings, ignore_warnings): continue file_pattern = test.get("filePattern", ".*") - file_pattern = re.compile(file_pattern) + file_pattern = compile_pattern(file_pattern) yield Test( name=test["name"], - pattern=re.compile(test["pattern"], re.MULTILINE), + pattern=compile_pattern(test["pattern"]), hint=test.get("hint"), file_pattern=file_pattern, error=test.get("error", True) or fail_warnings, diff --git a/relint/parse.py b/relint/parse.py index dbee513..ba2a2d5 100644 --- a/relint/parse.py +++ b/relint/parse.py @@ -1,7 +1,7 @@ from __future__ import annotations import collections -import regex as re +import re from rich import print as rprint from rich.console import Group @@ -9,9 +9,23 @@ from rich.panel import Panel from rich.syntax import Syntax -GIT_DIFF_LINE_NUMBERS_PATTERN = re.compile(r"@ -\d+(,\d+)? \+(\d+)(,)?(\d+)? @") -GIT_DIFF_FILENAME_PATTERN = re.compile(r"(?:\n|^)diff --git a\/.* b\/(.*)(?:\n|$)") -GIT_DIFF_SPLIT_PATTERN = re.compile(r"(?:\n|^)diff --git a\/.* b\/.*(?:\n|$)") +try: + import regex as re_fallback +except ImportError: + re_fallback = None + +def compile_pattern(pattern): + try: + return re.compile(pattern, re.MULTILINE) + except re.error: + if re_fallback: + return re_fallback.compile(pattern, re_fallback.MULTILINE) + else: + raise + +GIT_DIFF_LINE_NUMBERS_PATTERN = compile_pattern(r"@ -\d+(,\d+)? \+(\d+)(,)?(\d+)? @") +GIT_DIFF_FILENAME_PATTERN = compile_pattern(r"(?:\n|^)diff --git a\/.* b\/(.*)(?:\n|$)") +GIT_DIFF_SPLIT_PATTERN = compile_pattern(r"(?:\n|^)diff --git a\/.* b\/.*(?:\n|$)") def lint_file(filename, tests): @@ -65,7 +79,7 @@ def parse_line_numbers(output): def parse_filenames(output): - return re.findall(GIT_DIFF_FILENAME_PATTERN, output) + return GIT_DIFF_FILENAME_PATTERN.findall(output) def split_diff_content_by_filename(output: str) -> {str: str}: From 1262eb1d44e33bcb8f91e95e986107a8c7f6409a Mon Sep 17 00:00:00 2001 From: Chentao Yang Date: Wed, 7 Aug 2024 23:41:11 +0200 Subject: [PATCH 09/17] Adding tests for regex --- relint/__init__.py | 9 ++++++--- tests/fixtures/.relint.yml | 7 +++++++ tests/test_parse.py | 32 +++++++++++++++++++++++++++++++- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/relint/__init__.py b/relint/__init__.py index b397188..6ed1e3e 100644 --- a/relint/__init__.py +++ b/relint/__init__.py @@ -1,6 +1,9 @@ """Write your own linting rules using regular expressions.""" -from . import _version +try: + from . import _version +except ImportError: + _version = None -__version__ = _version.version -VERSION = _version.version_tuple +__version__ = getattr(_version, 'version', 'unknown') +VERSION = getattr(_version, 'version_tuple', (0, 0, 0)) diff --git a/tests/fixtures/.relint.yml b/tests/fixtures/.relint.yml index d7dec61..9e63e96 100644 --- a/tests/fixtures/.relint.yml +++ b/tests/fixtures/.relint.yml @@ -35,3 +35,10 @@ - name: no hint pattern: '(?i)hint' filePattern: ^(?!.*test_).*\.(py|js)$ + +# regex for more complicated regex patterns +- name: no line longer than 120 characters in a line (excluding comments) # by @yangcht + pattern: '(?\n" + "/* This is an extremely long COMMENT that has over one hundred and twenty characters to test whether this is recognized by the regex or not. */\n" + "int main() {\n" + " std::cout << \"This is an extremely long CODE that has over one hundred and twenty characters to test whether this is recognized by the regex or not.\"\n" + " return 0;\n" + "}\n" + ) + + with (fixture_dir / ".relint.yml").open() as fs: + config = fs.read() + tmpdir.join(".relint.yml").write(config) + + # Load the configuration as Test named tuples + tests = list(load_config(tmpdir.join(".relint.yml"), fail_warnings=False, ignore_warnings=False)) + + print(f"Loaded tests: {tests}") + print(f"Content of the file: {cc_file.read()}") + + with tmpdir.as_cwd(): + matches = list(lint_file(str(cc_file), tests)) + print(f"Matches found: {matches}") + assert len(matches) > 0 + assert any("no line longer than 120 characters in a line" in match[1].name for match in matches) From 4b0ee32f2b6482bbc446876b5bbbea18d9704f42 Mon Sep 17 00:00:00 2001 From: Chentao Yang Date: Wed, 7 Aug 2024 23:47:14 +0200 Subject: [PATCH 10/17] revert --- relint/__init__.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/relint/__init__.py b/relint/__init__.py index 6ed1e3e..4a43ddb 100644 --- a/relint/__init__.py +++ b/relint/__init__.py @@ -1,9 +1,6 @@ """Write your own linting rules using regular expressions.""" -try: - from . import _version -except ImportError: - _version = None +from . import _version -__version__ = getattr(_version, 'version', 'unknown') -VERSION = getattr(_version, 'version_tuple', (0, 0, 0)) +__version__ = _version.version +VERSION = _version.version_tuple \ No newline at end of file From 49049396918889ca7e1e3ad65ca926d2ff799261 Mon Sep 17 00:00:00 2001 From: Chentao Yang Date: Wed, 7 Aug 2024 23:49:08 +0200 Subject: [PATCH 11/17] revert --- relint/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relint/__init__.py b/relint/__init__.py index 4a43ddb..b397188 100644 --- a/relint/__init__.py +++ b/relint/__init__.py @@ -3,4 +3,4 @@ from . import _version __version__ = _version.version -VERSION = _version.version_tuple \ No newline at end of file +VERSION = _version.version_tuple From 65208e07bc9fc31868163618209146a8d24960d3 Mon Sep 17 00:00:00 2001 From: Johannes Maron Date: Fri, 9 Aug 2024 16:35:40 +0200 Subject: [PATCH 12/17] Cleanup patch submission --- .github/workflows/ci.yml | 21 ++++++++++++++++++++- pyproject.toml | 4 +++- relint/config.py | 28 ++++++++-------------------- relint/parse.py | 22 +++++++++------------- tests/fixtures/.relint.yml | 7 ------- tests/test_parse.py | 36 +++++++++++++++++++++++++----------- 6 files changed, 65 insertions(+), 53 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 12dbec4..e22ee38 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -63,9 +63,28 @@ jobs: - run: py.test --cov=. - uses: codecov/codecov-action@v4 + + extras: + runs-on: ubuntu-latest + strategy: + matrix: + extras: + - "regex" + + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.x" + - run: python -m pip install --upgrade pip setuptools + - run: python -m pip install -e .[test,${{ matrix.extras }}] + - run: relint --version + - run: py.test --cov=. + - uses: codecov/codecov-action@v4 + analyze: name: CodeQL Analyze - needs: [PyTest] + needs: [PyTest,extras] runs-on: ubuntu-latest permissions: actions: read diff --git a/pyproject.toml b/pyproject.toml index 39f026b..1b4345d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,7 +35,9 @@ test = [ "pytest-cov", "pytest-mock", ] -extra = ["regex"] +regex = [ + "regex" +] [project.scripts] relint = "relint.__main__:main" diff --git a/relint/config.py b/relint/config.py index 61ae487..1f26931 100644 --- a/relint/config.py +++ b/relint/config.py @@ -1,8 +1,14 @@ import collections import warnings +try: + import regex as re +except ImportError: + import re + import yaml + from .exceptions import ConfigError Test = collections.namedtuple( @@ -16,24 +22,6 @@ ), ) -try: - import re - re_compile = re.compile -except ImportError: - re_compile = None - -def compile_pattern(pattern): - try: - return re_compile(pattern, re.MULTILINE) - except (re.error, AttributeError) as e: - try: - import regex - except ImportError: - import subprocess - import sys - subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'regex']) - import regex - return regex.compile(pattern, regex.MULTILINE) def load_config(path, fail_warnings, ignore_warnings): with open(path) as fs: @@ -43,10 +31,10 @@ def load_config(path, fail_warnings, ignore_warnings): continue file_pattern = test.get("filePattern", ".*") - file_pattern = compile_pattern(file_pattern) + file_pattern = re.compile(file_pattern) yield Test( name=test["name"], - pattern=compile_pattern(test["pattern"]), + pattern=re.compile(test["pattern"]), hint=test.get("hint"), file_pattern=file_pattern, error=test.get("error", True) or fail_warnings, diff --git a/relint/parse.py b/relint/parse.py index ba2a2d5..3aab21c 100644 --- a/relint/parse.py +++ b/relint/parse.py @@ -1,7 +1,11 @@ from __future__ import annotations import collections -import re + +try: + import regex as re +except ImportError: + import re from rich import print as rprint from rich.console import Group @@ -14,18 +18,10 @@ except ImportError: re_fallback = None -def compile_pattern(pattern): - try: - return re.compile(pattern, re.MULTILINE) - except re.error: - if re_fallback: - return re_fallback.compile(pattern, re_fallback.MULTILINE) - else: - raise -GIT_DIFF_LINE_NUMBERS_PATTERN = compile_pattern(r"@ -\d+(,\d+)? \+(\d+)(,)?(\d+)? @") -GIT_DIFF_FILENAME_PATTERN = compile_pattern(r"(?:\n|^)diff --git a\/.* b\/(.*)(?:\n|$)") -GIT_DIFF_SPLIT_PATTERN = compile_pattern(r"(?:\n|^)diff --git a\/.* b\/.*(?:\n|$)") +GIT_DIFF_LINE_NUMBERS_PATTERN = re.compile(r"@ -\d+(,\d+)? \+(\d+)(,)?(\d+)? @") +GIT_DIFF_FILENAME_PATTERN = re.compile(r"(?:\n|^)diff --git a\/.* b\/(.*)(?:\n|$)") +GIT_DIFF_SPLIT_PATTERN = re.compile(r"(?:\n|^)diff --git a\/.* b\/.*(?:\n|$)") def lint_file(filename, tests): @@ -95,7 +91,7 @@ def split_diff_content_by_filename(output: str) -> {str: str}: """ content_by_filename = {} filenames = parse_filenames(output) - split_content = re.split(GIT_DIFF_SPLIT_PATTERN, output) + split_content = GIT_DIFF_SPLIT_PATTERN.split(output) split_content = filter(lambda x: x != "", split_content) for filename, content in zip(filenames, split_content): diff --git a/tests/fixtures/.relint.yml b/tests/fixtures/.relint.yml index 9e63e96..d7dec61 100644 --- a/tests/fixtures/.relint.yml +++ b/tests/fixtures/.relint.yml @@ -35,10 +35,3 @@ - name: no hint pattern: '(?i)hint' filePattern: ^(?!.*test_).*\.(py|js)$ - -# regex for more complicated regex patterns -- name: no line longer than 120 characters in a line (excluding comments) # by @yangcht - pattern: '(?\n" "/* This is an extremely long COMMENT that has over one hundred and twenty characters to test whether this is recognized by the regex or not. */\n" "int main() {\n" - " std::cout << \"This is an extremely long CODE that has over one hundred and twenty characters to test whether this is recognized by the regex or not.\"\n" + ' std::cout << "This is an extremely long CODE that has over one hundred and twenty characters to test whether this is recognized by the regex or not."\n' " return 0;\n" "}\n" ) @@ -197,13 +198,26 @@ def test_cc_linting_rule(tmpdir, fixture_dir): tmpdir.join(".relint.yml").write(config) # Load the configuration as Test named tuples - tests = list(load_config(tmpdir.join(".relint.yml"), fail_warnings=False, ignore_warnings=False)) - - print(f"Loaded tests: {tests}") - print(f"Content of the file: {cc_file.read()}") with tmpdir.as_cwd(): - matches = list(lint_file(str(cc_file), tests)) - print(f"Matches found: {matches}") + matches = list( + lint_file( + str(cc_file), + [ + Test( + name="No line longer than 120 characters", + pattern=regex.compile( + "(? 0 - assert any("no line longer than 120 characters in a line" in match[1].name for match in matches) + assert any( + "no line longer than 120 characters in a line" in match[1].name + for match in matches + ) From 0491fab3160520cb84226e08ca615c54d9313866 Mon Sep 17 00:00:00 2001 From: Johannes Maron Date: Fri, 9 Aug 2024 16:38:12 +0200 Subject: [PATCH 13/17] slim down test --- tests/test_parse.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tests/test_parse.py b/tests/test_parse.py index 841eaf3..a79b157 100644 --- a/tests/test_parse.py +++ b/tests/test_parse.py @@ -200,14 +200,14 @@ def test_cc_linting_rule(tmpdir, fixture_dir): # Load the configuration as Test named tuples with tmpdir.as_cwd(): - matches = list( + assert list( lint_file( str(cc_file), [ Test( name="No line longer than 120 characters", pattern=regex.compile( - "(? 0 - assert any( - "no line longer than 120 characters in a line" in match[1].name - for match in matches - ) From 378f306cd5e2f8aea3bd00515eca8325f316846a Mon Sep 17 00:00:00 2001 From: Johannes Maron Date: Fri, 9 Aug 2024 16:39:21 +0200 Subject: [PATCH 14/17] sort imports --- relint/config.py | 1 - tests/test_parse.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/relint/config.py b/relint/config.py index 1f26931..5e9046e 100644 --- a/relint/config.py +++ b/relint/config.py @@ -8,7 +8,6 @@ import yaml - from .exceptions import ConfigError Test = collections.namedtuple( diff --git a/tests/test_parse.py b/tests/test_parse.py index a79b157..5777d9b 100644 --- a/tests/test_parse.py +++ b/tests/test_parse.py @@ -4,6 +4,7 @@ import pytest from relint.__main__ import main +from relint.config import Test from relint.exceptions import ConfigError from relint.parse import ( lint_file, @@ -13,7 +14,6 @@ parse_line_numbers, split_diff_content_by_filename, ) -from relint.config import Test class TestParseGitDiff: @@ -210,7 +210,7 @@ def test_cc_linting_rule(tmpdir, fixture_dir): r".{120,}(? Date: Fri, 9 Aug 2024 16:42:53 +0200 Subject: [PATCH 15/17] Drop re_fallback --- relint/parse.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/relint/parse.py b/relint/parse.py index 3aab21c..07a5267 100644 --- a/relint/parse.py +++ b/relint/parse.py @@ -13,11 +13,6 @@ from rich.panel import Panel from rich.syntax import Syntax -try: - import regex as re_fallback -except ImportError: - re_fallback = None - GIT_DIFF_LINE_NUMBERS_PATTERN = re.compile(r"@ -\d+(,\d+)? \+(\d+)(,)?(\d+)? @") GIT_DIFF_FILENAME_PATTERN = re.compile(r"(?:\n|^)diff --git a\/.* b\/(.*)(?:\n|$)") From 0b56dd6d24c9950112ff7cb70a237b3b84c7ee2b Mon Sep 17 00:00:00 2001 From: Johannes Maron Date: Fri, 9 Aug 2024 16:44:28 +0200 Subject: [PATCH 16/17] Drop extra newline --- relint/parse.py | 1 - 1 file changed, 1 deletion(-) diff --git a/relint/parse.py b/relint/parse.py index 07a5267..192f3b2 100644 --- a/relint/parse.py +++ b/relint/parse.py @@ -13,7 +13,6 @@ from rich.panel import Panel from rich.syntax import Syntax - GIT_DIFF_LINE_NUMBERS_PATTERN = re.compile(r"@ -\d+(,\d+)? \+(\d+)(,)?(\d+)? @") GIT_DIFF_FILENAME_PATTERN = re.compile(r"(?:\n|^)diff --git a\/.* b\/(.*)(?:\n|$)") GIT_DIFF_SPLIT_PATTERN = re.compile(r"(?:\n|^)diff --git a\/.* b\/.*(?:\n|$)") From 9491c723299530131beae43af8ef607ba1b30a64 Mon Sep 17 00:00:00 2001 From: Johannes Maron Date: Fri, 9 Aug 2024 17:47:18 +0200 Subject: [PATCH 17/17] Update readme to include new extra --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 6bb6eb8..e8ffccf 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ ```shell-session python3 -m pip install relint +# or, if you have super advanced linting expressions +python3 -m pip install relint[regex] ``` ## [Examples & Recipes – The reLint Cookbook](https://github.com/codingjoe/relint/blob/main/COOKBOOK.md)