Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Script to add new rule file #123

Merged
merged 23 commits into from
Sep 10, 2020
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ build/
docs/source/rules/
coverage.xml
coverage_report.html
.idea/
50 changes: 47 additions & 3 deletions docs/source/build_a_lint_rule.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,50 @@
"Iteration order of attributes is the same as the order they appear in the source code.\n",
"In this case, that means visit_If_test is called before visit_If_body and visit_If_orelse.\n",
"\n",
"Use fixit's cli to generate a skeleton of adding a new rule file::\n",
"\n",
" $ python -m fixit.cli.add_new_rule # Creates new_rule.py at fixit/rules/new_rule.py\n",
" $ python -m fixit.cli.add_new_rule --path fixit/rules/my_rule.py # Creates rule file at path specified\n",
"\n",
"This will generate a model rule file used to create new rule."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"pycharm": {
"name": "#%%\n"
}
},
"outputs": [],
"source": [
"import libcst as cst\n",
"import libcst.matchers as m\n",
"\n",
"from fixit import CstLintRule, InvalidTestCase as Invalid, ValidTestCase as Valid\n",
"\n",
"class Rule(CstLintRule):\n",
" \"\"\"\n",
" docstring or new_rule description\n",
" \"\"\"\n",
"\n",
" MESSAGE = \"Enter rule description message\"\n",
"\n",
" VALID = [Valid(\"'example'\")] # Valid examples\n",
"\n",
" INVALID = [Invalid(\"'example'\")] # Invalid examples\n",
" ..."
]
},
acharles7 marked this conversation as resolved.
Show resolved Hide resolved
{
"cell_type": "raw",
"metadata": {
"raw_mimetype": "text/restructuredtext"
},
"source": [
"Use above structure to create a new rule. \n",
"\n",
acharles7 marked this conversation as resolved.
Show resolved Hide resolved
"The Declarative Matcher API\n",
"===========================\n",
"\n",
Expand Down Expand Up @@ -307,7 +351,7 @@
}
],
"metadata": {
"celltoolbar": "Edit Metadata",
"celltoolbar": "Raw Cell Format",
"kernelspec": {
"display_name": "Python 3",
"language": "python",
Expand All @@ -323,9 +367,9 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.5"
"version": "3.7.0b1"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
}
225 changes: 218 additions & 7 deletions docs/source/getting_started.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,16 @@
"metadata": {
"nbsphinx": "hidden"
},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"env: PYTHONPATH=/Users/lomesh/open-source/Fixit\n",
"/var/folders/dk/x6hpyx3d3555d6d0b6nhszjw0000gn/T/tmp4x7t6a68\n"
]
}
],
"source": [
"import tempfile\n",
"temp_dir = tempfile.TemporaryDirectory()\n",
Expand Down Expand Up @@ -70,7 +79,17 @@
"metadata": {
"nbsphinx": "hidden"
},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"/bin/sh: pyre: command not found\n",
"Initialized empty Git repository in /private/var/folders/dk/x6hpyx3d3555d6d0b6nhszjw0000gn/T/tmp4x7t6a68/.git/\n",
"/bin/sh: pyre: command not found\n"
]
}
],
"source": [
"FILE_NAME = \"example.py\"\n",
"from pathlib import Path\n",
Expand All @@ -96,7 +115,41 @@
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Scanning 1 files\n",
"Testing 23 rules\n",
"\n",
"Encountered exception <class 'Exception'> for the following paths:\n",
"./example.py\n",
"\u001b[93mRunning `pyre start` may solve the issue.\u001b[00m\n",
"example.py:4:1\n",
" NoInheritFromObjectRule: Inheriting from object is a no-op. 'class Foo:' is\n",
" just fine =)\n",
"example.py:5:12\n",
" UsePlusForStringConcatRule: Implicit string concatenation detected, please\n",
" add '+' to be explicit. E.g. a tuple or a call (\"a\" \"b\") with a missing\n",
" comma results in multiple strings being concatenated as one string and\n",
" causes unexpected behaviour.\n",
"example.py:10:16\n",
" ComparePrimitivesByEqualRule: Don't use `is` or `is not` to compare\n",
" primitives, as they compare references. Use == or != instead.\n",
"example.py:13:25\n",
" RewriteToComprehensionRule: It's unnecessary to use a list comprehension\n",
" inside a call to dict since there are equivalent comprehensions for this\n",
" type\n",
"example.py:10:16\n",
" F632: use ==/!= to compare constant literals (str, bytes, int, float, tuple)\n",
"example.py:13:80\n",
" E501: line too long (85 > 79 characters)\n",
"\n",
"Found 6 reports in 1 files in 1.37 seconds.\n"
]
}
],
"source": [
"! python -m fixit.cli.run_rules"
]
Expand All @@ -116,7 +169,82 @@
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Scanning 1 files\n",
"./example.py\n",
"\n",
"Encountered exception <class 'Exception'> for the following paths:\n",
"./example.py\n",
"\u001b[93mRunning `pyre start` may solve the issue.\u001b[00m\n",
"example.py:4:1 [applied fix]\n",
" NoInheritFromObjectRule: Inheriting from object is a no-op. 'class Foo:' is\n",
" just fine =)\n",
"Encountered exception <class 'Exception'> for the following paths:\n",
"./example.py\n",
"example.py\n",
"example.py\n",
"\u001b[93mRunning `pyre start` may solve the issue.\u001b[00m\n",
"example.py:5:12 [applied fix]\n",
" UsePlusForStringConcatRule: Implicit string concatenation detected, please\n",
" add '+' to be explicit. E.g. a tuple or a call (\"a\" \"b\") with a missing\n",
" comma results in multiple strings being concatenated as one string and\n",
" causes unexpected behaviour.\n",
"Encountered exception <class 'Exception'> for the following paths:\n",
"./example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"\u001b[93mRunning `pyre start` may solve the issue.\u001b[00m\n",
"example.py:10:16 [applied fix]\n",
" ComparePrimitivesByEqualRule: Don't use `is` or `is not` to compare\n",
" primitives, as they compare references. Use == or != instead.\n",
"Encountered exception <class 'Exception'> for the following paths:\n",
"./example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"\u001b[93mRunning `pyre start` may solve the issue.\u001b[00m\n",
"example.py:13:25 [applied fix]\n",
" RewriteToComprehensionRule: It's unnecessary to use a list comprehension\n",
" inside a call to dict since there are equivalent comprehensions for this\n",
" type\n",
"Encountered exception <class 'Exception'> for the following paths:\n",
"./example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"example.py\n",
"\u001b[93mRunning `pyre start` may solve the issue.\u001b[00m\n",
"\u001b[1mreformatted -\u001b[0m\n",
"\u001b[1mAll done! ✨ 🍰 ✨\u001b[0m\n",
"\u001b[1m1 file reformatted\u001b[0m.\u001b[0m\n",
"\n",
"Found 4 reports in 1 files in 6.57 seconds.\n"
]
}
],
"source": [
"! python -m fixit.cli.apply_fix"
]
Expand All @@ -134,7 +262,37 @@
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1mdiff --git a/example.py b/example.py\u001b[m\r\n",
"\u001b[1mindex aed4bb5..3f667f8 100644\u001b[m\r\n",
"\u001b[1m--- a/example.py\u001b[m\r\n",
"\u001b[1m+++ b/example.py\u001b[m\r\n",
"\u001b[36m@@ -1,14 +1,14 @@\u001b[m\r\n",
" from typing import Dict\u001b[m\r\n",
" \u001b[m\r\n",
" \u001b[m\r\n",
"\u001b[31m-class C(object):\u001b[m\r\n",
"\u001b[31m- attr = \"ab\" \"cd\" \"ef\" \"gh\"\u001b[m\r\n",
"\u001b[32m+\u001b[m\u001b[32mclass C:\u001b[m\r\n",
"\u001b[32m+\u001b[m\u001b[32m attr = \"ab\" + \"cd\" + \"ef\" + \"gh\"\u001b[m\r\n",
" \u001b[m\r\n",
" def method(self) -> Dict[int, str]:\u001b[m\r\n",
" filtered_char = []\u001b[m\r\n",
" for char in self.attr:\u001b[m\r\n",
"\u001b[31m- if char is not \"a\":\u001b[m\r\n",
"\u001b[32m+\u001b[m\u001b[32m if char != \"a\":\u001b[m\r\n",
" filtered_char.append(char)\u001b[m\r\n",
" \u001b[m\r\n",
"\u001b[31m- index_to_char = dict([(idx, char) for idx, char in enumerate(filtered_char)])\u001b[m\r\n",
"\u001b[32m+\u001b[m\u001b[32m index_to_char = {idx: char for idx, char in enumerate(filtered_char)}\u001b[m\r\n",
" return index_to_char\u001b[m\r\n"
]
}
],
"source": [
"! git diff"
]
Expand Down Expand Up @@ -287,7 +445,60 @@
"\n",
"- For more detailes on this script's usage, run::\n",
"\n",
" python -m fixit.cli.insert_suppressions --help"
" python -m fixit.cli.insert_suppressions --help\n",
" \n",
" \n",
"Creating New Rules\n",
"================== \n",
"\n",
"If you wish to create a new rule then, we have provided a script to make a general model for adding new rule in fixit module. To do this, run"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[1mAll done! ✨ 🍰 ✨\u001b[0m\n",
"1 file left unchanged.\u001b[0m\n",
"Successfully created my_rule.py rule file at fixit/rules\n",
"# Copyright (c) Facebook, Inc. and its affiliates.\n",
"#\n",
"# This source code is licensed under the MIT license found in the\n",
"# LICENSE file in the root directory of this source tree.\n",
"\n",
"\n",
"import libcst as cst\n",
"import libcst.matchers as m\n",
"\n",
"from fixit import CstLintRule, InvalidTestCase as Invalid, ValidTestCase as Valid\n",
"\n",
"\n",
"\"\"\"\n",
"This is a model rule file for adding a new rule to fixit module\n",
"\"\"\"\n",
"\n",
"\n",
"class Rule(CstLintRule):\n",
" \"\"\"\n",
" docstring or new_rule description\n",
" \"\"\"\n",
"\n",
" MESSAGE = \"Enter rule description message\"\n",
"\n",
" VALID = [Valid(\"'example'\")]\n",
"\n",
" INVALID = [Invalid(\"'example'\")]\n"
]
}
],
"source": [
"! python -m fixit.cli.add_new_rule --path fixit/rules/my_rule.py\n",
"! cat fixit/rules/my_rule.py"
]
},
{
Expand Down Expand Up @@ -319,7 +530,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.5"
"version": "3.7.0b1"
}
},
"nbformat": 4,
Expand Down
Loading