Compare commits

...

747 Commits

Author SHA1 Message Date
Charlie Marsh
cf56955ba6 Bump version to 0.0.227 2023-01-19 23:24:52 -05:00
Charlie Marsh
8a8939afd8 Avoid checking row types for single-name @parametrize decorators (#2013)
Closes #2008.
2023-01-19 22:13:17 -05:00
Martin Fischer
6acf2accc6 Improve --explain output
Previous output for `ruff --explain E711`:

    E711 (pycodestyle): Comparison to `None` should be `cond is None`

New output:

    none-comparison

    Code: E711 (pycodestyle)

    Autofix is always available.

    Message formats:

    * Comparison to `None` should be `cond is None`
    * Comparison to `None` should be `cond is not None`
2023-01-19 22:08:00 -05:00
Charlie Marsh
ec0c7647ab Avoid SIM401 in elif blocks (#2012)
For now, we're just gonna avoid flagging this for `elif` blocks, following the same reasoning as for ternaries. We can handle all of these cases, but we'll knock out the TODOs as a pair, and this avoids broken code.

Closes #2007.
2023-01-19 21:57:18 -05:00
Charlie Marsh
045229630e Upgrade RustPython (#2011)
This lets us revert the "manual" fix introduced in #1944.
2023-01-19 21:49:12 -05:00
Martin Fischer
c600991905 Change AsRef<str> impl for Rule to kebab-case
As we surface rule names more to users we want
them to be easier to type than PascalCase.

Prior art:

Pylint and ESLint also use kebab-case for their rule names.
Clippy uses snake_case but only for syntactical reasons
(so that the argument to e.g. #![allow(clippy::some_lint)]
can be parsed as a path[1]).

[1]: https://doc.rust-lang.org/reference/paths.html
2023-01-19 21:37:11 -05:00
Charlie Marsh
f6a93a4c3d Enable autofix for FitsOnOneLine (D200) (#2006)
Closes #1965.
2023-01-19 19:24:50 -05:00
Aarni Koskela
de54ff114e Add RUF005 "unpack instead of concatenating" check (#1957)
This PR adds a new check that turns expressions such as `[1, 2, 3] + foo` into `[1, 2, 3, *foo]`, since the latter is easier to read and faster:

```
~ $ python3.11 -m timeit -s 'b = [6, 5, 4]' '[1, 2, 3] + b'
5000000 loops, best of 5: 81.4 nsec per loop
~ $ python3.11 -m timeit -s 'b = [6, 5, 4]' '[1, 2, 3, *b]'
5000000 loops, best of 5: 66.2 nsec per loop
```

However there's a couple of gotchas:

* This felt like a `simplify` rule, so I borrowed an unused `SIM` code even if the upstream `flake8-simplify` doesn't do this transform. If it should be assigned some other code, let me know 😄 
* **More importantly** this transform could be unsafe if the other operand of the `+` operation has overridden `__add__` to do something else. What's the `ruff` policy around potentially unsafe operations? (I think some of the suggestions other ported rules give could be semantically different from the original code, but I'm not sure.)
* I'm not a very established Rustacean, so there's no doubt my code isn't quite idiomatic. (For instance, is there a neater way to write that four-way `match` statement?)

Thanks for `ruff`, by the way! :)
2023-01-19 17:38:17 -05:00
Charlie Marsh
64b398c72b Tweak some instructions in CONTRIBUTING.md 2023-01-19 17:17:39 -05:00
Aarni Koskela
c99bd3fa60 Split up pydocstyle rules (#2003)
As per @not-mAs per @not-my-profile's [comment](https://github.com/charliermarsh/ruff/pull/1999#discussion_r1081579337):

> we actually want to break up such rules.rs files into smaller files

this breaks up `pydocstyle/rules.rs` into a directory.y-profile's [comment](https://github.com/charliermarsh/ruff/pull/1999#discussion_r1081579337):

> we actually want to break up such rules.rs files into smaller files

this breaks up `pydocstyle/rules.rs` into a directory.
2023-01-19 13:17:25 -05:00
Martin Fischer
8ac930f886 Fix that --explain panics
This commit fixes a bug accidentally introduced in
6cf770a692,
which resulted every `ruff --explain <code>` invocation to fail with:

    thread 'main' panicked at 'Mismatch between definition and access of `explain`.
    Could not downcast to ruff::registry::Rule, need to downcast to &ruff::registry::Rule',
    ruff_cli/src/cli.rs:184:18

We also add an integration test for --explain to prevent such bugs from
going by unnoticed in the future.
2023-01-19 12:58:44 -05:00
Charlie Marsh
ad80fdc2cd Avoid SIM201 and SIM202 errors in __ne__ et al (#2001)
Closes #1986.
2023-01-19 11:27:27 -05:00
Aarni Koskela
a0ea8fe22f Apply #[derive(Default)] fixes suggested by Clippy (#2000)
These were bugging me every time I ran `clippy` 😁
2023-01-19 11:04:43 -05:00
Martin Fischer
3c3da8a88c derive-msg-formats 5/5: Remove placeholder implementations
# This commit has been generated via the following Python script:
# (followed by `cargo +nightly fmt` and `cargo dev generate-all`)
# For the reasoning see the previous commit(s).

import re
import sys

for path in (
    'src/violations.rs',
    'src/rules/flake8_tidy_imports/banned_api.rs',
    'src/rules/flake8_tidy_imports/relative_imports.rs',
):
    with open(path) as f:
        text = ''

        while line := next(f, None):

            if line.strip() != 'fn message(&self) -> String {':
                text += line
                continue

            text += '    #[derive_message_formats]\n' + line

            body = next(f)
            while (line := next(f)) != '    }\n':
                body += line

            # body = re.sub(r'(?<!code\| |\.push\()format!', 'format!', body)
            body = re.sub(
                r'("[^"]+")\s*\.to_string\(\)', r'format!(\1)', body, re.DOTALL
            )
            body = re.sub(
                r'(r#".+?"#)\s*\.to_string\(\)', r'format!(\1)', body, re.DOTALL
            )

            text += body + '    }\n'

            while (line := next(f)).strip() != 'fn placeholder() -> Self {':
                text += line
            while (line := next(f)) != '    }\n':
                pass

    with open(path, 'w') as f:
        f.write(text)
2023-01-19 11:03:32 -05:00
Martin Fischer
16e79c8db6 derive-msg-formats 4/5: Implement #[derive_message_formats]
The idea is nice and simple we replace:

    fn placeholder() -> Self;

with

    fn message_formats() -> &'static [&'static str];

So e.g. if a Violation implementation defines:

    fn message(&self) -> String {
        format!("Local variable `{name}` is assigned to but never used")
    }

it would also have to define:

   fn message_formats() -> &'static [&'static str] {
       &["Local variable `{name}` is assigned to but never used"]
   }

Since we however obviously do not want to duplicate all of our format
strings we simply introduce a new procedural macro attribute
#[derive_message_formats] that can be added to the message method
declaration in order to automatically derive the message_formats
implementation.

This commit implements the macro. The following and final commit
updates violations.rs to use the macro. (The changes have been separated
because the next commit is autogenerated via a Python script.)
2023-01-19 11:03:32 -05:00
Martin Fischer
8f6d8e215c derive-msg-formats 3/5: Introduce Violation::AUTOFIX associated constant
ruff_dev::generate_rules_table previously documented which rules are
autofixable via DiagnosticKind::fixable ... since the DiagnosticKind was
obtained via Rule::kind (and Violation::placeholder) which we both want
to get rid of we have to obtain the autofixability via another way.

This commit implements such another way by adding an AUTOFIX
associated constant to the Violation trait. The constant is of the type
Option<AutoFixkind>, AutofixKind is a new struct containing an
Availability enum { Sometimes, Always}, letting us additionally document
that some autofixes are only available sometimes (which previously
wasn't documented). We intentionally introduce this information in a
struct so that we can easily introduce further autofix metadata in the
future such as autofix applicability[1].

[1]: https://doc.rust-lang.org/stable/nightly-rustc/rustc_errors/enum.Applicability.html
2023-01-19 11:03:32 -05:00
Martin Fischer
8993baab01 derive-msg-formats 2/5: Remove DiagnosticKind::summary
While ruff displays the string returned by Violation::message in its
output for detected violations the messages displayed in the README
and in the `--explain <code>` output previously used the
DiagnosticKind::summary() function which for some verbose messages
provided shorter descriptions.

This commit removes DiagnosticKind::summary, and moves the more
extensive documentation into doc comments ... these are not displayed
yet to the user but doing that is very much planned.
2023-01-19 11:03:32 -05:00
Martin Fischer
2568627c4c derive-msg-formats 1/5: Remove unnecessary usages of Rule::kind
This commit series removes the following associated
function from the Violation trait:

    fn placeholder() -> Self;

ruff previously used this placeholder approach for the messages it
listed in the README and displayed when invoked with --explain <code>.

This approach is suboptimal for three reasons:

1. The placeholder implementations are completely boring code since they
   just initialize the struct with some dummy values.

2. Displaying concrete error messages with arbitrary interpolated values
   can be confusing for the user since they might not recognize that the
   values are interpolated.

3. Some violations have varying format strings depending on the
   violation which could not be documented with the previous approach
   (while we could have changed the signature to return Vec<Self> this
   would still very much suffer from the previous two points).

We therefore drop Violation::placeholder in favor of a new macro-based
approach, explained in commit 4/5.

Violation::placeholder is only invoked via Rule::kind, so we firstly
have to get rid of all Rule::kind invocations ... this commit starts
removing the trivial cases.
2023-01-19 11:03:32 -05:00
Martin Fischer
9603a024b3 refactor: Move a bunch of pandas-vet logic to rules::pandas_vet 2023-01-19 11:03:32 -05:00
Charlie Marsh
a122d95ef5 Preserve unmatched comparators in SIM109 (#1998)
Closes #1993.
2023-01-19 10:23:20 -05:00
Damien Allen
6ddfe50ac4 Added pylint formatter (#1995)
Fixes: #1953

@charliermarsh thank you for the tips in the issue.

I'm not very familiar with Rust, so please excuse if my string formatting syntax is messy.

In terms of testing, I compared output of `flake8 --format=pylint ` and `cargo run --format=pylint` on the same code and the output syntax seems to check out.
2023-01-19 08:01:27 -05:00
Martin Fischer
26901a78c9 Make define_rule_mapping! set rule code as doc comment of variants
Since the UI still relies on the rule codes this improves the developer
experience by letting developers view the code of a Rule enum variant by
hovering over it.
2023-01-19 07:37:16 -05:00
Martin Fischer
6649225167 rule 8/8: Automatically rewrite RuleCode to Rule
# This commit was automatically generated by running the following
# script (followed by `cargo +nightly fmt`):

import glob
import re
from typing import NamedTuple

class Rule(NamedTuple):
    code: str
    name: str
    path: str

def rules() -> list[Rule]:
    """Returns all the rules defined in `src/registry.rs`."""
    file = open('src/registry.rs')

    rules = []

    while next(file) != 'ruff_macros::define_rule_mapping!(\n':
        continue

    while (line := next(file)) != ');\n':
        line = line.strip().rstrip(',')
        if line.startswith('//'):
            continue
        code, path = line.split(' => ')
        name = path.rsplit('::')[-1]
        rules.append(Rule(code, name, path))

    return rules

code2name = {r.code: r.name for r in rules()}

for pattern in ('src/**/*.rs', 'ruff_cli/**/*.rs', 'ruff_dev/**/*.rs', 'scripts/add_*.py'):
    for name in glob.glob(pattern, recursive=True):
        with open(name) as f:
            text = f.read()

        text = re.sub('Rule(?:Code)?::([A-Z]\w+)', lambda m: 'Rule::' + code2name[m.group(1)], text)
        text = re.sub(r'(?<!"<FilePattern>:<)RuleCode\b', 'Rule', text)
        text = re.sub('(use crate::registry::{.*, Rule), Rule(.*)', r'\1\2', text) # fix duplicate import

        with open(name, 'w') as f:
            f.write(text)
2023-01-18 23:51:48 -05:00
Martin Fischer
9e3083aa2c rule 7/8: Change Rule enum definition 2023-01-18 23:51:48 -05:00
Martin Fischer
6d11ff3822 rule 6/8: Remove Serialize & Deserialize impls for Rule 2023-01-18 23:51:48 -05:00
Martin Fischer
6cf770a692 rule 5/8: Remove FromStr impl for Rule 2023-01-18 23:51:48 -05:00
Martin Fischer
3534e370e1 rule 4/8: Remove Display impl for Rule 2023-01-18 23:51:48 -05:00
Martin Fischer
dbcab5128c rule 3/8: Remove AsRef<str> impl for Rule 2023-01-18 23:51:48 -05:00
Martin Fischer
3810250bb6 rule 2/8: Rename DiagnosticKind::code to rule 2023-01-18 23:51:48 -05:00
Martin Fischer
3c1c1e1dd3 rule 1/8: Rename RuleCode to Rule (backwards-compatible for now)
This commit series refactors ruff to decouple "rules" from "rule codes",
in order to:

1. Make our code more readable by changing e.g.
   RuleCode::UP004 to Rule::UselessObjectInheritance.

2. Let us cleanly map multiple codes to one rule, for example:

   [UP004] in pyupgrade, [R0205] in pylint and [PIE792] in flake8-pie
   all refer to the rule UselessObjectInheritance but ruff currently
   only associates that rule with the UP004 code (since the
   implementation was initially modeled after pyupgrade).

3. Let us cleanly map one code to multiple rules, for example:

   [C0103] from pylint encompasses N801, N802 and N803 from pep8-naming.

The latter two steps are not yet implemented by this commit series
but this refactoring enables us to introduce such a mapping.  Such a
mapping would also let us expand flake8_to_ruff to support e.g. pylint.

After the next commit which just does some renaming the following four
commits remove all trait derivations from the Rule (previously RuleCode)
enum that depend on the variant names to guarantee that they are not
used anywhere anymore so that we can rename all of these variants in the
eigth and final commit without breaking anything.

While the plan very much is to also surface these human-friendly names
more in the user interface this is not yet done in this commit series,
which does not change anything about the UI: it's purely a refactor.

[UP004]: pyupgrade doesn't actually assign codes to its messages.
[R0205]: https://pylint.pycqa.org/en/latest/user_guide/messages/refactor/useless-object-inheritance.html
[PIE792]: https://github.com/sbdchd/flake8-pie#pie792-no-inherit-object
[C0103]: https://pylint.pycqa.org/en/latest/user_guide/messages/convention/invalid-name.html
2023-01-18 23:51:48 -05:00
Martin Fischer
5b7bd93b91 refactor: Use Self:: in match arms 2023-01-18 23:51:48 -05:00
Martin Fischer
9e096b4a4c refactor: Make define_rule_mapping! generate RuleCodePrefix directly 2023-01-18 23:51:48 -05:00
Charlie Marsh
d8645acd1f Bump version to 0.0.226 2023-01-18 20:54:38 -05:00
Charlie Marsh
92dd073191 Add Pylint settings to lib_wasm.rs 2023-01-18 20:54:03 -05:00
Charlie Marsh
ff96219e62 Exclude None, Bool, and Ellipsis from ConstantType (#1988)
These have no effect, so it's confusing that they're even settable.
2023-01-18 20:50:09 -05:00
Charlie Marsh
d33424ec9d Enable suppression of magic values by type (#1987)
Closes #1949.
2023-01-18 20:44:24 -05:00
Charlie Marsh
34412a0a01 Avoid removing side effects for boolean simplifications (#1984)
Closes #1978.
2023-01-18 19:08:14 -05:00
Charlie Marsh
ceb48d3a32 Use relative paths for INP001 (#1981) 2023-01-18 18:45:47 -05:00
Charlie Marsh
969a6f0d53 Replace misplaced-comparison-constant with SIM300 (#1980)
Closes: #1954.
2023-01-18 18:42:49 -05:00
Charlie Marsh
7628876ff2 Invert order of yoda-conditions message (#1979)
The suggestion was wrong!
2023-01-18 18:27:36 -05:00
Charlie Marsh
ef355e5c2c Remove artificial wraps from GitHub messages (#1977) 2023-01-18 18:20:56 -05:00
Charlie Marsh
97f55b8e97 Convert remaining call path sites to use SmallVec (#1972) 2023-01-18 14:50:33 -05:00
Aarni Koskela
ff2be35f51 Run cargo fmt in pre-commit (#1968)
Since `cargo fmt` is a required CI check, we could just as well run it in `pre-commit`.
2023-01-18 13:14:51 -05:00
Anders Kaseorg
1e803f7108 README: Link “Flake8” for consistency with the rest of the list (#1969)
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-18 13:07:21 -05:00
Charlie Marsh
1ab0273aa7 Strip whitespace when injecting D209 newline (#1967)
Closes #1963.
2023-01-18 12:09:17 -05:00
Charlie Marsh
5a7d8c25f4 Treat subscript accesses as unsafe effects for autofix (#1966)
See: #1809.
2023-01-18 11:46:12 -05:00
Charlie Marsh
26d6414558 Fix UP003 check from rebase 2023-01-18 11:39:39 -05:00
Charlie Marsh
dae95626ae Use smallvec for call path representation (#1960)
This provides a ~10% speed-up for large codebases with `--select ALL`:

![Screen Shot 2023-01-18 at 11 28 20 AM](https://user-images.githubusercontent.com/1309177/213236389-cff50840-6e55-47a3-9164-2e40cbc885f6.png)
2023-01-18 11:29:05 -05:00
Maksudul Haque
9a3e525930 [isort] Add no-lines-before Option (#1955)
Closes https://github.com/charliermarsh/ruff/issues/1916.
2023-01-18 11:09:47 -05:00
Anders Kaseorg
b9c6cfc0ab Autofix SIM117 (MultipleWithStatements) (#1961)
This is slightly buggy due to Instagram/LibCST#855; it will complain `[ERROR] Failed to fix nested with: Failed to extract CST from source` when trying to fix nested parenthesized `with` statements lacking trailing commas. But presumably people who write parenthesized `with` statements already knew that they don’t need to nest them.

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-18 11:06:04 -05:00
Charlie Marsh
b1f10c8339 Confine type-of-primitive checks to builtin type calls (#1962)
Closes #1958.
2023-01-18 10:53:50 -05:00
Anders Kaseorg
83346de6e0 Autofix SIM102 (NestedIfStatements)
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-18 07:37:27 -05:00
Anders Kaseorg
b23cc31863 Change ast::helpers::has_coments to accept a Range
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-18 07:37:27 -05:00
Anders Kaseorg
462d81beb7 Ensure ast::whitespace::indentation extracts whitespace
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-18 07:37:27 -05:00
Anders Kaseorg
715ea2d374 Accept a Locator for ast::whitespace::indentation
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-18 07:37:27 -05:00
skykasko
6c7e60b4f9 Fix bad link for flake8-no-pep420 (#1952)
See https://github.com/charliermarsh/ruff/pull/1942.
2023-01-18 07:36:05 -05:00
Maksudul Haque
868d0b3e29 [isort] Add constants and variables Options (#1951)
closes https://github.com/charliermarsh/ruff/issues/1819
2023-01-18 07:30:51 -05:00
Charlie Marsh
cdb4700813 Bump version to 0.0.225 2023-01-18 00:22:48 -05:00
Anders Kaseorg
ea4d54a90f Restrict SIM105 to try blocks with a body of one simple statement (#1948)
If a `try` block has multiple statements, a compound statement, or
control flow, rewriting it with `contextlib.suppress` would obfuscate
the fact that the exception still short-circuits further statements in
the block.

Fixes #1947.

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-18 00:22:22 -05:00
Charlie Marsh
51b917cfbf Exempt contextlib.ExitStack() for SIM115 rules (#1946)
Since our binding tracking is somewhat limited, I opted to favor false negatives over false positives. So, e.g., this won't trigger SIM115:

```py
with contextlib.ExitStack():
    f = exit_stack.enter_context(open("filename"))
```

(Notice that `exit_stack` is unbound.)

The alternative strategy required us to incorrectly trigger SIM115 on this:

```py
with contextlib.ExitStack() as exit_stack:
    exit_stack_ = exit_stack
    f = exit_stack_.enter_context(open("filename"))
```

Closes #1945.
2023-01-17 22:39:54 -05:00
Edgar R. M
c880d744fd Implement flake8-no-pep420 (#1942)
Closes https://github.com/charliermarsh/ruff/issues/1844.
2023-01-17 22:10:32 -05:00
Charlie Marsh
84d1df08be Avoid broken autofix for SIM103 with elif (#1944)
Also adjusts the generator to avoid the extra parentheses (and skips commented `if` statements).

Closes #1943.
2023-01-17 22:03:17 -05:00
Charlie Marsh
b9bb5acff8 Remove unnecessary setuptools block 2023-01-17 21:17:37 -05:00
Charlie Marsh
ca7c3c2175 Avoid autofixing comma rules when --fix is not set (#1940)
Closes #1939.
2023-01-17 20:09:01 -05:00
Charlie Marsh
8891e2e62b Fix name of ruff-pre-commit event 2023-01-17 17:25:02 -05:00
Martin Fischer
53265e0ed4 cli: Catch panics to tell the user to report them (#1928) 2023-01-17 17:17:09 -05:00
Charlie Marsh
072849a8a9 Move @functools.cache rewrites to their own rule (#1938)
Closes #1934.
2023-01-17 15:12:40 -05:00
Charlie Marsh
70ea4b25e8 Allow duplicate enum values for enum.auto() (#1933)
Closes #1932.
2023-01-17 11:14:11 -05:00
Martin Fischer
30e133f3d8 refactor: Declare defaults once in settings::defaults 2023-01-17 09:20:57 -05:00
Martin Fischer
aa812de07e refactor: Implement Default for Settings 2023-01-17 09:20:57 -05:00
Martin Fischer
57ac6a8444 refactor: Make resolve_codes take IntoIterator instead of Iterator 2023-01-17 09:20:57 -05:00
Martin Fischer
a6566b1b34 refactor: Merge Settings.enabled and Settings.fixable
The Settings struct previously contained the fields:

     pub enabled: HashableHashSet<RuleCode>,
     pub fixable: HashableHashSet<RuleCode>,

This commit merges both fields into one by introducing a new
RuleTable type, wrapping HashableHashMap<RuleCode, bool>,
which has the following benefits:

1. It makes the invalid state that a rule is
   disabled but fixable unrepresentable.

2. It encapsulates the implementation details of the table.
   (It currently uses an FxHashMap but that may change.)

3. It results in more readable code.

       settings.rules.enabled(rule)
       settings.rules.should_fix(rule)

   is more readable than:

       settings.enabled.contains(rule)
       settings.fixable.contains(rule)
2023-01-17 09:20:57 -05:00
Martin Fischer
580da1fa6b refactor: Group Settings fields 2023-01-17 09:20:57 -05:00
Martin Fischer
b78b6f275e refactor: Define origin names & URLs within doc comments 2023-01-17 07:44:40 -05:00
Martin Fischer
6868bb46f5 refactor: Get rid of Platform enum 2023-01-17 07:44:40 -05:00
Martin Fischer
601848d9a8 refactor: Rename RuleOrigin::title to RuleOrigin::name 2023-01-17 07:44:40 -05:00
Martin Fischer
f4da7635f0 Add missing url for flake8-import-conventions 2023-01-17 07:44:40 -05:00
Charlie Marsh
74a8a218f3 Bump version to 0.0.224 2023-01-16 23:43:14 -05:00
Colin Delahunty
1730f2a603 [pyupgrade] Automatically rewrite format-strings to f-strings (#1905) 2023-01-16 23:06:39 -05:00
Charlie Marsh
a4862857de Update PIE796 fixture 2023-01-16 19:29:14 -05:00
Leonardo Esparis
6e88c60c46 Add flake8-pie PIE796: prefer-unique-enum (#1923)
I accept any suggestion. By the way, I have a doubt, I have checked and all flake8-pie plugins can be fixed by ruff, but is it necessary that this one is also fixed automatically ?

rel #1543
2023-01-16 19:27:34 -05:00
Charlie Marsh
2ed1f78873 Add benchmark scripts for no-IO (#1925) 2023-01-16 17:38:40 -05:00
Charlie Marsh
f3bf008aed Avoid removing statements that contain side-effects (#1920)
Closes #1917.
2023-01-16 14:45:02 -05:00
Charlie Marsh
3b4aaa53c1 Add some new testimonials (#1921) 2023-01-16 14:44:52 -05:00
Charlie Marsh
6abf71639f Avoid syntax errors when fixing parenthesized unused variables (#1919)
Closes #1917.
2023-01-16 14:27:41 -05:00
Charlie Marsh
c0845a8c28 Rewrite lru_cache to cache on Python 3.9+ (#1918)
Closes #1913.
2023-01-16 13:14:27 -05:00
Paul Barrett
019ecc4add Trigger update to pre-commit mirror after pypi publish (#1910) 2023-01-16 13:14:18 -05:00
Martin Fischer
f4cf48d885 refactor: Move rule-specific details out of mod.rs via type aliases 2023-01-16 11:27:24 -05:00
Martin Fischer
005f5d7911 refactor: Make flake8_tidy_imports::Settings derive Default 2023-01-16 11:27:24 -05:00
Martin Fischer
2fce580693 refactor: Move flake8_tidy_imports Settings to mod.rs 2023-01-16 11:27:24 -05:00
Martin Fischer
8862565a0f refactor: Split ruff::rules::flake8_tidy_imports::rules 2023-01-16 11:27:24 -05:00
Martin Fischer
5bf6da0db7 refactor: Rename BannedRelativeImport to RelativeImports
The idea is to follow the Rust naming convention for lints[1]:

> the lint name should make sense when read as
> "allow lint-name" or "allow lint-name items"

Following that convention prefixing "Banned" is
redundant as it could be prefixed to any lint name.

[1]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints
2023-01-16 11:27:24 -05:00
Martin Fischer
ee655c1a88 refactor: Rename BannedApi to ApiBan to distinguish it from the violation struct 2023-01-16 11:27:24 -05:00
Harutaka Kawamura
2236b4bd59 Add backticks to B904's message (#1914)
This PR adds backticks to B904's message to improve readability.


Without backticks:

<img width="1480" alt="image" src="https://user-images.githubusercontent.com/17039389/212682457-71f13de9-e3dd-4ead-a82b-98e5b60653c2.png">

With backticks:

<img width="1480" alt="image" src="https://user-images.githubusercontent.com/17039389/212682775-36868401-b63e-47d1-ae25-b43b61866b6c.png">
2023-01-16 11:12:43 -05:00
Charlie Marsh
fbf311f7d5 Add instructions for Pyupgrade benchmark 2023-01-16 03:21:31 -05:00
Martin Fischer
8c18b28bc4 Derive Hash instead of implementing it by hand
The caching mechanism of the CLI (ruff_cli::cache) relies on
ruff::settings::Settings implementing the Hash trait.

The ruff::settings::Settings struct previously couldn't automatically
derive the Hash implementation via the #[derive(Hash)] macro attribute
since some of its field types intentionally[1][2] don't implement Hash
(namely regex::Regex, globset::GlobMatcher and globset::GlobSet and
HashMap and HashSet from the standard library).

The code therefore previously implemented the Hash trait by hand for the
whole struct. Implementing Hash by hand for structs that are subject to
change is a bad idea since it's very easy to forget to update the Hash
implementation when adding a new field to the struct. And the Hash
implementation indeed was already incorrect by omitting several fields
from the hash.

This commit introduces wrapper types for Regex, GlobMatcher, GlobSet,
HashSet & HashMap that implement Hash so that we can still add
#[derive(Hash)] to the Settings struct, guaranteeing a correct hash
implementation.

[1]: https://github.com/rust-lang/regex/issues/364#issuecomment-301082076
[2]: The standard library doesn't impl<T: Hash + Ord> Hash for HashSet<T>
     presumably since sorted() requires an allocation and Hash
     implementations are generally expected to work without allocations.
2023-01-16 01:42:55 -05:00
Charlie Marsh
42031b8574 Re-run benchmark and update documentation (#1907)
Closes #269.
2023-01-16 01:38:58 -05:00
Charlie Marsh
3a3a5fcd81 Remove -dev suffix from flake8_to_ruff 2023-01-15 22:45:14 -05:00
Charlie Marsh
e8577d5e26 Bump version to 0.0.223 2023-01-15 22:44:01 -05:00
Charlie Marsh
bcb1e6ba20 Add flake8-commas to the README 2023-01-15 22:43:29 -05:00
Charlie Marsh
15403522c1 Avoid triggering SIM117 for async with statements (#1903)
Actually, it looks like _none_ of the existing rules should be triggered on async `with` statements.

Closes #1902.
2023-01-15 21:42:36 -05:00
messense
cb4f305ced Lock stdout once when printing diagnostics (#1901)
https://doc.rust-lang.org/stable/std/io/struct.Stdout.html

> Each handle shares a global buffer of data to be written to the standard output stream.
> Access is also synchronized via a lock and
> explicit control over locking is available via the [`lock`](https://doc.rust-lang.org/stable/std/io/struct.Stdout.html#method.lock) method.
2023-01-15 21:04:00 -05:00
Charlie Marsh
d71a615b18 Buffer diagnostic writes to stdout (#1900) 2023-01-15 19:34:15 -05:00
Charlie Marsh
dfc2a34878 Remove rogue println 2023-01-15 18:59:59 -05:00
Charlie Marsh
7608087776 Don't require docstrings for setters and deleters (#1899) 2023-01-15 18:57:38 -05:00
Charlie Marsh
228f033e15 Skip noqa checker if no diagnostics are found (#1898) 2023-01-15 18:53:00 -05:00
Martin Fischer
d75d6d7c7c refactor: Split CliSettings from Settings
We want to automatically derive Hash for the library settings, which
requires us to split off all the settings unused by the library
(since these shouldn't affect the hash used by ruff_cli::cache).
2023-01-15 15:19:42 -05:00
Martin Fischer
ef80ab205c Mark Settings::for_rule(s) as test-only 2023-01-15 15:19:42 -05:00
Ran Benita
d3041587ad Implement flake8-commas (#1872)
Implements [flake8-commas](https://github.com/PyCQA/flake8-commas). Fixes #1058.

The plugin is mostly redundant with Black (and also deprecated upstream), but very useful for projects which can't/won't use an auto-formatter. 

This linter works on tokens. Before porting to Rust, I cleaned up the Python code ([link](https://gist.github.com/bluetech/7c5dcbdec4a73dd5a74d4bc09c72b8b9)) and made sure the tests pass. In the Rust version I tried to add explanatory comments, to the best of my understanding of the original logic.

Some changes I did make:

- Got rid of rule C814 - "missing trailing comma in Python 2". Ruff doesn't support Python 2.
- Merged rules C815 - "missing trailing comma in Python 3.5+" and C816 - "missing trailing comma in Python 3.6+" into C812 - "missing trailing comma". These Python versions are outdated, didn't think it was worth the complication.
- Added autofixes for C812 and C819.

Autofix is missing for C818 - "trailing comma on bare tuple prohibited". It needs to turn e.g. `x = 1,` into `x = (1, )`, it's a bit difficult to do with tokens only, so I skipped it for now.

I ran the rules on cpython/Lib and on a big internal code base and it works as intended (though I only sampled the diffs).
2023-01-15 14:03:32 -05:00
Harutaka Kawamura
8d912404b7 Use more precise error ranges for RET505~508 (#1895) 2023-01-15 13:54:24 -05:00
Tom Fryers
85bdb45eca Improve magic value message wording (#1892)
The message previously specified 'number', but the error applies to more types.
2023-01-15 12:53:02 -05:00
messense
c7d0d26981 Update add plugin/rule scripts (#1889)
Adjusted some file locations and changed to use [`pathlib`](https://docs.python.org/3/library/pathlib.html) instead of `os.path`.
2023-01-15 12:49:42 -05:00
Charlie Marsh
5c6753e69e Remove some Clippy allows (#1888) 2023-01-15 02:32:36 -05:00
Charlie Marsh
3791ca721a Add a dedicated token indexer for continuations and comments (#1886)
The primary motivation is that we can now robustly detect `\` continuations due to the addition of `Tok::NonLogicalNewline`. This PR generalizes the approach we took to comments (track all lines that contain any comments), and applies it to continuations too.
2023-01-15 01:57:31 -05:00
Charlie Marsh
2c644619e0 Convert confusable violations to named fields (#1887)
See: #1871.
2023-01-15 01:56:18 -05:00
Martin Fischer
81996f1bcc Convert define_rule_mapping! to a procedural macro
define_rule_mapping! was previously implemented as a declarative macro,
which was however partially relying on an origin_by_code! proc macro
because declarative macros cannot match on substrings of identifiers.

Currently all define_rule_mapping! lines look like the following:

    TID251 => violations::BannedApi,
    TID252 => violations::BannedRelativeImport,

We want to break up violations.rs, moving the violation definitions to
the respective rule modules. To do this we want to change the previous
lines to:

    TID251 => rules::flake8_tidy_imports::banned_api::BannedApi,
    TID252 => rules::flake8_tidy_imports::relative_imports::RelativeImport,

This however doesn't work because the define_rule_mapping! macro is
currently defined as:

    ($($code:ident => $mod:ident::$name:ident,)+) => { ... }

That is it only supported $module::$name but not longer paths with
multiple modules. While we could define `=> $path:path`[1] then we
could no longer access the last path segment, which we need because
we use it for the DiagnosticKind variant names. And
`$path:path::$last:ident` doesn't work either because it would be
ambiguous (Rust wouldn't know where the path ends ... so path fragments
have to be followed by some punctuation/keyword that may not be part of
paths). And we also cannot just introduce a procedural macro like
path_basename!(...) because the following is not valid Rust code:

    enum Foo { foo!(...), }

(macros cannot be called in the place where you define variants.)

So we have to convert define_rule_mapping! into a proc macro in order to
support paths of arbitrary length and this commit implements that.

[1]: https://doc.rust-lang.org/reference/macros-by-example.html#metavariables
2023-01-15 01:54:57 -05:00
Charlie Marsh
e3cc918b93 Bump version to 0.0.222 2023-01-14 23:34:53 -05:00
Charlie Marsh
d864477876 Turn doc references into links (#1878) 2023-01-14 23:27:45 -05:00
Charlie Marsh
e1ced89624 Document breaking --max-complexity change 2023-01-14 23:22:38 -05:00
Martin Fischer
4470d7ba04 Make the CI check for broken links in the Rust docs (#1883) 2023-01-14 23:18:17 -05:00
Harutaka Kawamura
2a1601749f Fix range of SIM201, 202, and 208 (#1880)
Before

```
resources/test/fixtures/flake8_simplify/SIM208.py:1:13: SIM208 Use `a` instead of `not (not a)`
  |
1 | if not (not a):  # SIM208
  |             ^ SIM208
  |
  = help: Replace with `a`

resources/test/fixtures/flake8_simplify/SIM208.py:4:14: SIM208 Use `a == b` instead of `not (not a == b)`
  |
4 | if not (not (a == b)):  # SIM208
  |              ^^^^^^ SIM208
  |
  = help: Replace with `a == b`
```

After

```
resources/test/fixtures/flake8_simplify/SIM208.py:1:4: SIM208 Use `a` instead of `not (not a)`
  |
1 | if not (not a):  # SIM208
  |    ^^^^^^^^^^^ SIM208
  |
  = help: Replace with `a`

resources/test/fixtures/flake8_simplify/SIM208.py:4:4: SIM208 Use `a == b` instead of `not (not a == b)`
  |
4 | if not (not (a == b)):  # SIM208
  |    ^^^^^^^^^^^^^^^^^^ SIM208
  |
  = help: Replace with `a == b`
```
2023-01-14 21:17:32 -05:00
Charlie Marsh
a01edad1c4 Remove --max-complexity from the CLI (#1877) 2023-01-14 18:27:23 -05:00
Martin Fischer
a81ac6705d Make ruff::source_code::{Generator, Locator, Stylist} private 2023-01-14 18:23:59 -05:00
Martin Fischer
d77675f30d Make ruff::{ast, autofix, directives, rustpython_helpers} private 2023-01-14 18:23:59 -05:00
Martin Fischer
fe7658199d Make ruff::violations private 2023-01-14 18:23:59 -05:00
Martin Fischer
cfa25ea4b0 Make ruff::rules private 2023-01-14 18:23:59 -05:00
Martin Fischer
c7f0f3b237 Regenerate insta snapshots 2023-01-14 11:48:02 -05:00
Martin Fischer
3b36030461 Introduce ruff::rules module
Resolves #1547.
2023-01-14 11:48:02 -05:00
Charlie Marsh
812df77246 Add Dagster and SnowCLI 2023-01-14 10:45:16 -05:00
Martin Fischer
69b356e9b9 Add top-level doc comments for crates
Test by running:

    cargo doc --no-deps --all --open
2023-01-14 10:11:30 -05:00
Martin Fischer
033d7d7e91 Disable doc generation for the ruff_cli binary 2023-01-14 10:11:30 -05:00
Martin Fischer
a181ca7a3d Reduce the API of ruff_cli to ruff_cli::help() 2023-01-14 10:11:30 -05:00
Martin Fischer
92124001d5 Turn ruff_dev into a bin-only crate 2023-01-14 10:11:30 -05:00
Martin Fischer
06b389c5bc Turn flake8_to_ruff into a bin-only crate 2023-01-14 10:11:30 -05:00
Thomas MK
9dc66b5a65 Split up the table corresponding to the pylint rules (#1868)
This makes it easier to see which rules you're enabling when selecting
one of the pylint codes (like `PLC`). This also makes it clearer what
those abbreviations stand for. When I first saw the pylint section, I
was very confused by that, so other might be as well.

See it rendered here:
https://github.com/thomkeh/ruff/blob/patch-1/README.md#pylint-plc-ple-plr-plw
2023-01-14 08:07:02 -05:00
Ran Benita
3447dd3615 Bump RustPython (#1836)
This bumps RustPython so we can use the new `NonLogicalNewline` token.
A couple of rules needed a fix due to the new token. There might be more
that are not caught by tests (anything working with tokens directly with
lookaheads), I hope not.
2023-01-14 08:03:27 -05:00
Harutaka Kawamura
42cb106377 Improve SIM117 (#1867)
This PR makes the following changes to improve `SIM117`:

- Avoid emitting `SIM117` multiple times within the same `with`
statement:
- Adjust the error range.  


## Example

```python
with A() as a:  # SIM117
    with B() as b:
        with C() as c:
            print("hello")
```

### Current

```
resources/test/fixtures/flake8_simplify/SIM117.py:5:1: SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements
  |
5 | / with A() as a:  # SIM117
6 | |     with B() as b:
7 | |         with C() as c:
8 | |             print("hello")
  | |__________________________^ SIM117
  |

resources/test/fixtures/flake8_simplify/SIM117.py:6:5: SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements
  |
6 |       with B() as b:
  |  _____^
7 | |         with C() as c:
8 | |             print("hello")
  | |__________________________^ SIM117
  |
```

### Improved

```
resources/test/fixtures/flake8_simplify/SIM117.py:5:1: SIM117 Use a single `with` statement with multiple contexts instead of nested `with` statements
  |
5 | / with A() as a:  # SIM117
6 | |     with B() as b:
7 | |         with C() as c:
  | |______________________^ SIM117
  |
```

Signed-off-by: harupy <hkawamura0130@gmail.com>
2023-01-14 07:59:24 -05:00
Charlie Marsh
027382f891 Add support for namespace packages (#1859)
Closes #1817.
2023-01-14 07:31:57 -05:00
Charlie Marsh
931d41bff1 Revert "Bump version to 0.0.222"
This reverts commit 852aab5758.
2023-01-13 23:56:29 -05:00
Charlie Marsh
852aab5758 Bump version to 0.0.222 2023-01-13 23:50:08 -05:00
Charlie Marsh
27fe4873f2 Fix placement of update feature flag 2023-01-13 23:46:32 -05:00
Charlie Marsh
ee6c81d02a Bump version to 0.0.221 2023-01-13 23:33:15 -05:00
Charlie Marsh
59542344e2 Avoid unnecessary allocations for module names (#1863) 2023-01-13 23:26:34 -05:00
Martin Fischer
7b1ce72f86 Actually fix wasm-pack build command (#1862)
I initially attempted to run `wasm-pack build -p ruff` which gave the
error message:

Error: crate directory is missing a `Cargo.toml` file; is `-p` the wrong
directory?

I interpreted that as wasm-pack looking for the "ruff" directory because
I specified -p ruff, however actually the wasm-pack build usage is:

    wasm-pack build [FLAGS] [OPTIONS] <path> <cargo-build-options>

And I was missing the `<path>` argument. So this actually wasn't at all
a bug in wasm-pack but just a confusing error message. And the symlink
hack I introduced in the previous commit didn't actually work ... I only
accidentally omitted the `-p` when testing (which ended up as `ruff`
being the <path> argument) ... CLIs are fun.
2023-01-13 23:20:20 -05:00
Martin Fischer
156e09536e Add workaround for wasm-pack bug to fix the playground CI (#1861)
Fixes #1860.
2023-01-13 22:46:51 -05:00
Charlie Marsh
22341c4ae4 Move repology down 2023-01-13 22:29:26 -05:00
Colin Delahunty
e4993bd7e2 Added ALE (#1857)
Fixes the sub issue I brought up in #1829.
2023-01-13 21:39:51 -05:00
Martin Fischer
82aff5f9ec Split off ruff_cli crate from ruff library
This lets you test the ruff linters or use the ruff library
without having to compile the ~100 additional dependencies
that are needed by the CLI.

Because we set the following in the [workspace] section of Cargo.toml:

   default-members = [".", "ruff_cli"]

`cargo run` still runs the CLI and `cargo test` still tests
the code in src/ as well as the code in the new ruff_cli crate.
(But you can now also run `cargo test -p ruff` to only test the linters.)
2023-01-13 21:37:54 -05:00
Charlie Marsh
403a004e03 Refactor import-tracking to leverage existing AST bindings (#1856)
This PR refactors our import-tracking logic to leverage our existing
logic for tracking bindings. It's both a significant simplification, a
significant improvement (as we can now track reassignments), and closes
out a bunch of subtle bugs.

Though the AST tracks all bindings (e.g., when parsing `import os as
foo`, we bind the name `foo` to a `BindingKind::Importation` that points
to the `os` module), when I went to implement import tracking (e.g., to
ensure that if the user references `List`, it's actually `typing.List`),
I added a parallel system specifically for this use-case.

That was a mistake, for a few reasons:

1. It didn't track reassignments, so if you had `from typing import
List`, but `List` was later overridden, we'd still consider any
reference to `List` to be `typing.List`.
2. It required a bunch of extra logic, include complex logic to try and
optimize the lookups, since it's such a hot codepath.
3. There were a few bugs in the implementation that were just hard to
correct under the existing abstractions (e.g., if you did `from typing
import Optional as Foo`, then we'd treat any reference to `Foo` _or_
`Optional` as `typing.Optional` (even though, in that case, `Optional`
was really unbound).

The new implementation goes through our existing binding tracking: when
we get a reference, we find the appropriate binding given the current
scope stack, and normalize it back to its original target.

Closes #1690.
Closes #1790.
2023-01-13 20:39:54 -05:00
Charlie Marsh
0b92849996 Improve spacing preservation for C405 fixes (#1855)
We now preserve the spacing of the more common form:

```py
set((
    1,
))
```

Rather than the less common form:

```py
set(
    (1,)
)
```
2023-01-13 13:11:08 -05:00
Charlie Marsh
12440ede9c Remove non-magic trailing comma from tuple (#1854)
Closes #1821.
2023-01-13 12:56:42 -05:00
max0x53
fc3f722df5 Implement PLR0133 (ComparisonOfConstants) (#1841)
This PR adds [Pylint
`R0133`](https://pylint.pycqa.org/en/latest/user_guide/messages/refactor/comparison-of-constants.html)

Feel free to suggest changes and additions, I have tried to maintain
parity with the Pylint implementation
[`comparison_checker.py`](https://github.com/PyCQA/pylint/blob/main/pylint/checkers/base/comparison_checker.py#L247)

See #970
2023-01-13 12:14:35 -05:00
Maksudul Haque
84ef7a0171 [isort] Add classes Config Option (#1849)
ref https://github.com/charliermarsh/ruff/issues/1819
2023-01-13 12:13:01 -05:00
Nicola Soranzo
66b1d09362 Clarify that some flake8-bugbear opinionated rules are already implemented (#1847)
E.g. B904 and B905.
2023-01-13 11:49:05 -05:00
Maksudul Haque
3ae01db226 [flake8-bugbear] Fix False Positives for B024 & B027 (#1851)
closes https://github.com/charliermarsh/ruff/issues/1848
2023-01-13 11:46:17 -05:00
Charlie Marsh
048e5774e8 Use absolute paths for --stdin-filename matching (#1843)
Non-basename glob matches (e.g., for `--per-file-ignores`) assume that
the path has been converted to an absolute path. (We do this for
filenames as part of the directory traversal.) For filenames passed via
stdin, though, we're missing this conversion. So `--per-file-ignores`
that rely on the _basename_ worked as expected, but directory paths did
not.

Closes #1840.
2023-01-12 21:01:05 -05:00
max0x53
b47e8e6770 Implement PLR2004 (MagicValueComparison) (#1828)
This PR adds [Pylint
`R2004`](https://pylint.pycqa.org/en/latest/user_guide/messages/refactor/magic-value-comparison.html#magic-value-comparison-r2004)

Feel free to suggest changes and additions, I have tried to maintain
parity with the Pylint implementation
[`magic_value.py`](https://github.com/PyCQA/pylint/blob/main/pylint/extensions/magic_value.py)

See #970
2023-01-12 19:44:18 -05:00
Jan Katins
ef17c82998 Document the way extend-ignore/select are applied (#1839)
Closes: https://github.com/charliermarsh/ruff/issues/1838
2023-01-12 19:44:03 -05:00
Charlie Marsh
9aeb5df5fe Bump version to 0.0.220 2023-01-12 17:57:04 -05:00
Charlie Marsh
7ffba7b552 Use absolute paths for GitHub and Gitlab annotations (#1837)
Note that the _annotation path_ is absolute, while the path encoded in
the message remains relative.

![Screen Shot 2023-01-12 at 5 54 11
PM](https://user-images.githubusercontent.com/1309177/212198531-63f15445-0f6a-471c-a64c-18ad2b6df0c7.png)

Closes #1835.
2023-01-12 17:54:34 -05:00
Charlie Marsh
06473bb1b5 Support for-else loops in SIM110 and SIM111 (#1834)
This PR adds support for `SIM110` and `SIM111` simplifications of the
form:

```py
def f():
    # SIM110
    for x in iterable:
        if check(x):
            return True
    else:
        return False
```
2023-01-12 17:04:58 -05:00
Ash Berlin-Taylor
bf5c048502 Airflow is now using ruff (#1833)
😀
2023-01-12 16:50:01 -05:00
Charlie Marsh
eaed08ae79 Skip SIM110/SIM111 fixes that create long lines 2023-01-12 16:21:54 -05:00
Charlie Marsh
e0fdc4c5e8 Avoid SIM110/SIM110 errors with else statements (#1832)
Closes #1831.
2023-01-12 16:17:27 -05:00
Charlie Marsh
590bec57f4 Fix typo in relative-imports-order option name 2023-01-12 15:57:58 -05:00
Charlie Marsh
3110d342c7 Implement isort's reverse_relative setting (#1826)
This PR implements `reverse-relative`, from isort, but renames it to
`relative-imports-order` with the respected value `closest-to-furthest`
and `furthest-to-closest`, and the latter being the default.

Closes #1813.
2023-01-12 15:48:40 -05:00
nefrob
39aae28eb4 📝 Update readme example for adding isort required imports (#1824)
Fixes use of  isort name to the ruff name.
2023-01-12 13:18:06 -05:00
Charlie Marsh
dcccfe2591 Avoid parsing pyproject.toml files when settings are fixed (#1827)
Apart from being wasteful, this can also cause problems (see the linked
issue).

Resolves #1812.
2023-01-12 13:15:44 -05:00
Martin Fischer
38f5e8f423 Decouple linter module from cache module 2023-01-12 13:09:59 -05:00
Martin Fischer
74f14182ea Decouple resolver module from cli::Overrides 2023-01-12 13:09:59 -05:00
Charlie Marsh
bbc1e7804e Don't trigger SIM401 for complex default values (#1825)
Resolves #1809.
2023-01-12 12:51:23 -05:00
messense
c6320b29e4 Implement autofix for flake8-quotes (#1810)
Resolves #1789
2023-01-12 12:42:28 -05:00
Maksudul Haque
1a90408e8c [flake8-bandit] Add Rule for S701 (jinja2 autoescape false) (#1815)
ref: https://github.com/charliermarsh/ruff/issues/1646

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-01-12 11:59:20 -05:00
Jeroen Van Goey
07134c50c8 Add usage of ruff in pandas to README (#1811)
pandas now uses ruff for linting, see
https://github.com/pandas-dev/pandas/pull/50160
2023-01-12 10:55:21 -05:00
Charlie Marsh
b36d4a15b0 Modify visibility and shuffle around some modules (#1807) 2023-01-11 23:57:05 -05:00
Charlie Marsh
d8162ce79d Bump version to 0.0.219 2023-01-11 23:46:01 -05:00
Charlie Marsh
e11ef54bda Improve globset documentation and help message (#1808)
Closes #1545.
2023-01-11 23:41:56 -05:00
messense
9a07b0623e Move top level ruff into python folder (#1806)
https://maturin.rs/project_layout.html#mixed-rustpython-project

Resolves #1805
2023-01-11 23:12:55 -05:00
Charlie Marsh
f450e2e79d Implement doc line length enforcement (#1804)
This PR implements `W505` (`DocLineTooLong`), which is similar to `E501`
(`LineTooLong`) but confined to doc lines.

I based the "doc line" definition on pycodestyle, which defines a doc
line as a standalone comment or string statement. Our definition is a
bit more liberal, since we consider any string statement a doc line
(even if it's part of a multi-line statement) -- but that seems fine to
me.

Note that, unusually, this rule requires custom extraction from both the
token stream (to find standalone comments) and the AST (to find string
statements).

Closes #1784.
2023-01-11 22:32:14 -05:00
Colin Delahunty
329946f162 Avoid erroneous Q002 error message for single-quote docstrings (#1777)
Fixes #1775. Before implementing your solution I thought of a slightly
simpler one. However, it will let this function pass:
```
def double_inside_single(a):
    'Double inside "single "'
```
If we want function to pass, my implementation works. But if we do not,
then I can go with how you suggested I implemented this (I left how I
would begin to handle it commented out). The bottom of the flake8-quotes
documentation seems to suggest that this should pass:
https://pypi.org/project/flake8-quotes/

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-01-11 20:01:54 -05:00
Charlie Marsh
588399e415 Fix Clippy error 2023-01-11 19:59:00 -05:00
Chammika Mannakkara
4523885268 flake8_simplify : SIM401 (#1778)
Ref #998 

- Implements SIM401 with fix
- Added tests

Notes: 
- only recognize simple ExprKind::Name variables in expr patterns for
now
- bug-fix from reference implementation: check 3-conditions (dict-key,
target-variable, dict-name) to be equal, `flake8_simplify` only test
first two (only first in second pattern)
2023-01-11 19:51:37 -05:00
Maksudul Haque
de81b0cd38 [flake8-simplify] Add Rule for SIM115 (Use context handler for opening files) (#1782)
ref: https://github.com/charliermarsh/ruff/issues/998

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-01-11 19:28:05 -05:00
Charlie Marsh
4fce296e3f Skip SIM108 violations for complex if-statements (#1802)
We now skip SIM108 violations if: the resulting statement would exceed
the user-specified line length, or the `if` statement contains comments.

Closes #1719.

Closes #1766.
2023-01-11 19:21:30 -05:00
Charlie Marsh
9d48d7bbd1 Skip unused argument checks for magic methods (#1801)
We still check `__init__`, `__call__`, and `__new__`.

Closes #1796.
2023-01-11 19:02:20 -05:00
Charlie Marsh
c56f263618 Avoid flagging builtins for OSError rewrites (#1800)
Related to (but does not fix) #1790.
2023-01-11 18:49:25 -05:00
Grzegorz Bokota
fb2382fbc3 Update readme to reflect #1763 (#1780)
When checking changes in the 0.0.218 release I noticed that auto fixing
PT004 and PT005 was disabled but this change was not reflected in
README. So I create this small PR to do this.

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-01-11 18:37:41 -05:00
Charlie Marsh
c92a5a8704 Avoid rewriting flake8-comprehensions expressions for builtin overrides (#1799)
Closes #1788.
2023-01-11 18:33:55 -05:00
Charlie Marsh
d7cf3147b7 Refactor flake8-comprehensions rules to take fewer arguments (#1797) 2023-01-11 18:21:18 -05:00
Charlie Marsh
bf4d35c705 Convert flake8-comprehensions checks to Checker style (#1795) 2023-01-11 18:11:20 -05:00
Charlie Marsh
4e97e9c7cf Improve PIE794 autofix behavior (#1794)
We now: (1) trigger PIE794 for objects without bases (not sure why this
was omitted before); and (2) remove the entire line, rather than leaving
behind trailing whitespace.

Resolves #1787.
2023-01-11 18:01:29 -05:00
Charlie Marsh
a3fcc3b28d Disable update check by default (#1786)
This has received enough criticism that I'm comfortable making it
opt-in.
2023-01-11 13:47:40 -05:00
Charlie Marsh
cfbd068dd5 Bump version to 0.0.218 2023-01-10 21:28:23 -05:00
Charlie Marsh
8aed23fe0a Avoid B023 false-positives for some common builtins (#1776)
This is based on the upstream work in
https://github.com/PyCQA/flake8-bugbear/pull/303 and
https://github.com/PyCQA/flake8-bugbear/pull/305/files.

Resolves #1686.
2023-01-10 21:23:48 -05:00
Colin Delahunty
c016c41c71 Pyupgrade: Format specifiers (#1594)
A part of #827. Posting this for visibility. Still has some work to do
to be done.

Things that still need done before this is ready:

- [x] Does not work when the item is being assigned to a variable
- [x] Does not work if being used in a function call
- [x] Fix incorrectly removed calls in the function
- [x] Has not been tested with pyupgrade negative test cases

Tests from pyupgrade can be seen here:
https://github.com/asottile/pyupgrade/blob/main/tests/features/format_literals_test.py

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-01-10 20:21:04 -05:00
Charlie Marsh
f1a5e53f06 Enable isort-style required-imports enforcement (#1762)
In isort, this is called `add-imports`, but I prefer the declarative
name.

The idea is that by adding the following to your `pyproject.toml`, you
can ensure that the import is included in all files:

```toml
[tool.ruff.isort]
required-imports = ["from __future__ import annotations"]
```

I mostly reverse-engineered isort's logic for making decisions, though I
made some slight tweaks that I think are preferable. A few comments:

- Like isort, we don't enforce this on empty files (like empty
`__init__.py`).
- Like isort, we require that the import is at the top-level.
- isort will skip any docstrings, and any comments on the first three
lines (I think, based on testing). Ruff places the import after the last
docstring or comment in the file preamble (that is: after the last
docstring or comment that comes before the _first_ non-docstring and
non-comment).

Resolves #1700.
2023-01-10 18:12:57 -05:00
Charlie Marsh
1e94e0221f Disable doctests (#1772)
We don't have any doctests, but `cargo test --all` spends more than half
the time on doctests? A little confusing, but this brings the test time
from > 4s to < 2s on my machine.
2023-01-10 15:10:16 -05:00
Martin Fischer
543865c96b Generate RuleCode::origin() via macro (#1770) 2023-01-10 13:20:43 -05:00
Maksudul Haque
b8e3f0bc13 [flake8-bandit] Add Rule for S508 (snmp insecure version) & S509 (snmp weak cryptography) (#1771)
ref: https://github.com/charliermarsh/ruff/issues/1646

Co-authored-by: messense <messense@icloud.com>
Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-01-10 13:13:54 -05:00
Charlie Marsh
643cedb200 Move CONTRIBUTING.md to top-level (#1768) 2023-01-10 07:38:12 -05:00
Charlie Marsh
91620c378a Disable release builds on CI (#1761) 2023-01-10 07:33:03 -05:00
Harutaka Kawamura
b732135795 Do not autofix PT004 and PT005 (#1763)
As @edgarrmondragon commented in
https://github.com/charliermarsh/ruff/pull/1740#issuecomment-1376230550,
just renaming fixture doesn't work.
2023-01-10 07:24:16 -05:00
messense
9384a081f9 Implement flake8-simplify SIM112 (#1764)
Ref #998
2023-01-10 07:24:01 -05:00
Charlie Marsh
edab268d50 Bump version to 0.0.217 2023-01-09 23:26:22 -05:00
Charlie Marsh
e4fad70a57 Update documentation to match latest terminology (#1760)
Closes #1759.
2023-01-09 21:10:47 -05:00
Charlie Marsh
1a09fff991 Update rule-generation scripts to match latest conventions (#1758)
Resolves #1755.
2023-01-09 19:55:46 -05:00
Charlie Marsh
b85105d2ec Add a helper for any-like operations (#1757) 2023-01-09 19:34:33 -05:00
Charlie Marsh
f7ac28a935 Omit sys.version_info and sys.platform checks from ternary rule (#1756)
Resolves #1753.
2023-01-09 19:22:34 -05:00
Charlie Marsh
9532f342a6 Enable project-specific typing module re-exports (#1754)
Resolves #1744.
2023-01-09 18:17:50 -05:00
Mohamed Daahir
0ee37aa0aa Cache build artifacts using Swatinem/rust-cache@v1 (#1750)
This GitHub Action caches build artifacts in addition to dependencies
which halves the CI duration time.

Resolves #1752.
2023-01-09 15:35:32 -05:00
Charlie Marsh
8a26c8b4e0 Fix wasm builds 2023-01-09 12:58:07 -05:00
Charlie Marsh
2cb59b0f45 Use dedicated warnings for flake8-to-ruff (#1748) 2023-01-09 12:48:06 -05:00
Charlie Marsh
2729f3d207 Add support for defining extra builtins (#1747)
Resolves #1745.
2023-01-09 12:24:28 -05:00
Charlie Marsh
59155ce9f6 Rename checks and plugins to rules (#1739) 2023-01-09 01:39:51 -05:00
Charlie Marsh
caf6c65de7 Bump version to 0.0.216 2023-01-09 01:14:28 -05:00
Matt Oberle
147d594b38 Add isort.force-sort-within-sections setting (#1635)
This commit is a first attempt at addressing issue #1003.

The default `isort` behavior is `force-sort-within-sections = false`,
which places `from X import Y` statements after `import X` statements.

When `force-sort-within-sections = true` all imports are sorted by
module name.

When module names are equivalent, the `import` statement comes before
the `from` statement.
2023-01-09 01:06:48 -05:00
Charlie Marsh
f18078a1eb Allow unused arguments for empty methods with docstrings (#1742)
Resolves #1741.
2023-01-09 00:34:07 -05:00
Harutaka Kawamura
fe4eb13601 Autofix PT004, PT005, PT024, and PT025 (#1740) 2023-01-08 22:41:00 -05:00
Charlie Marsh
161ab05533 Rename more local usages of check to diagnostic (#1738) 2023-01-08 18:10:08 -05:00
Charlie Marsh
2c537e24cc Move violation structs out of registry.rs (#1728) 2023-01-08 17:54:20 -05:00
Charlie Marsh
0fe349b5f8 Rename CheckCategory to RuleOrigin (#1726) 2023-01-08 17:50:18 -05:00
Charlie Marsh
09dc3c7225 Rename Check to Diagnostic (#1725)
Along with:

- `CheckKind` -> `DiagnosticKind`
- `CheckCode` -> `RuleCode`
- `CheckCodePrefix` -> `RuleCodePrefix`
2023-01-08 17:46:20 -05:00
Harutaka Kawamura
498134b7ee Audit unittest assert methods (#1736)
I ran the following code in Python 3.10 to automatically generate a list
of enums.

```python
import unittest

print(
    ",\n".join(
        sorted(
            m.removeprefix("assert") if m != "assert_" else "Underscore"
            for m in dir(unittest.TestCase)
            if m.startswith("assert")
        )
    )
)
```
2023-01-08 16:21:34 -05:00
Charlie Marsh
0152814a00 Bump version to 0.0.215 2023-01-07 22:17:29 -05:00
Harutaka Kawamura
0b3fab256b Remove assertNotContains (#1729)
`unittest.TestCase` doens't have a method named `assertNotContains`.
2023-01-07 22:15:48 -05:00
Chammika Mannakkara
212ce4d331 buf-fix: flake8_simplify SIM212 (#1732)
bug-fix in #1717

Use the correct `IfExprWithTwistedArms` struct.
2023-01-07 22:03:48 -05:00
Charlie Marsh
491b1e4968 Move RUFF_CACHE_DIR to Clap's env support (#1733) 2023-01-07 22:01:27 -05:00
Charlie Marsh
8b01b53d89 Move RUFF_CACHE_DIR to Clap's env support (#1733) 2023-01-07 22:01:20 -05:00
messense
f9a5867d3e Add RUFF_FORMAT environment variable support (#1731)
Resolves #1716
2023-01-07 21:54:19 -05:00
Harutaka Kawamura
4149627f19 Add more unittest assert methods to PT009 (#1730) 2023-01-07 21:52:48 -05:00
Charlie Marsh
7d24146df7 Implement --isolated CLI flag (#1727)
Closes #1724.
2023-01-07 18:43:58 -05:00
Charlie Marsh
1c6ef3666c Treat failures to fix TypedDict conversions as debug logs (#1723)
This also allows us to flag the error, even if we can't fix it.

Closes #1212.
2023-01-07 17:51:45 -05:00
Charlie Marsh
16d933fcf5 Respect isort:skip action comment (#1722)
Resolves: #1718.
2023-01-07 17:30:18 -05:00
Charlie Marsh
a9cc56b2ac Add ComparableExpr hierarchy for comparing expressions (#1721) 2023-01-07 17:29:21 -05:00
Charlie Marsh
4de6c26ff9 Automatically remove duplicate dictionary keys (#1710)
For now, to be safe, we're only removing keys with duplicate _values_.

See: #1647.
2023-01-07 16:16:42 -05:00
Charlie Marsh
98856e05d6 Fix clippy errors 2023-01-07 15:49:59 -05:00
Charlie Marsh
edf46c06d0 Bump version to 0.0.214 2023-01-07 15:34:45 -05:00
Chammika Mannakkara
9cfce61f36 flake8_simplify : SIM210, SIM211, SIM212 (#1717) 2023-01-07 15:32:34 -05:00
Charlie Marsh
bdb9a4d1a7 Update CONTRIBUTING.md to point to violations.rs (#1720) 2023-01-07 15:20:21 -05:00
Martin Fischer
82e0c0ced6 structs 9/9: Run cargo test and cargo insta accept 2023-01-07 15:14:58 -05:00
Martin Fischer
6a723b50c7 structs 8/9: Run cargo fix and cargo fmt 2023-01-07 15:14:58 -05:00
Martin Fischer
6208eb7bbf structs 7/9: Manually fix errors introduced in the previous commit 2023-01-07 15:14:58 -05:00
Martin Fischer
43db446dfa structs 6/9: Automatically change CheckKind::* to violations::*
The changes in this commit were generated by running:

for f in $(find src -name '*.rs'); do sed -Ei 's/use crate::registry::.*;/\0use crate::violations;/g' $f; done
for f in $(find src -name '*.rs'); do sed -Ei 's/CheckKind::([A-Z])/violations::\1/g' $f; done
git checkout src/registry.rs src/lib.rs src/lib_wasm.rs src/violations.rs
cargo +nightly fmt
2023-01-07 15:14:58 -05:00
Martin Fischer
3c8fdbf107 structs 5/9: Make Check::new call into() on the passed kind 2023-01-07 15:14:58 -05:00
Martin Fischer
54fb47ea6a structs 4/9: Implement define_rule_mapping! 2023-01-07 15:14:58 -05:00
Martin Fischer
efadfeda96 structs 3/9: Manually implement autofix_formatter for conditional autofixes 2023-01-07 15:14:58 -05:00
Martin Fischer
90198f7563 structs 2/9: Generate violations.rs from registry.rs
# The changes of this commit were generated using the following code:
# (followed by cargo +nightly fmt)

import re
import subprocess
import io

indent = ' ' * 4

def split_words(s):
    return re.split(r'\b', s)

def checkkind_match_arms(f, strip_some=False):
    bodies = {}

    while (line := next(f).rstrip()) != indent * 2 + '}':
        if line.lstrip().startswith('//'):
            continue

        if line.strip() == '':
            continue
        parts = line.split('=>', maxsplit=1)
        if parts[0].strip() == '_':
            break
        left, body = parts
        left = left.strip()
        body = body.strip()
        if body == '{':
            body = ''
            while (line := next(f).rstrip()) != indent * 3 + '}':
                body += line + '\n'
        else:
            body = body.rstrip(',')
        kind = split_words(left)[3]
        if strip_some:
            body = re.sub('\)$', '', re.sub(r'Some\(', '', body, 1).rstrip(), 1)
        if ('(' in left and not '(..)' in left) or '{' in left:
            body = (
                'let '
                + left.replace('CheckKind::', '').replace('CheckCode::', '')
                + ' = self;\n'
                + body
            )
        bodies[kind] = body

    return bodies

with open('src/registry.rs') as f:
    orig_registry_code = f.read()

    # simplify the parsing of multiline match arms
    registry_code = subprocess.check_output(
        ['rustfmt', '+nightly', '--config', 'force_multiline_blocks=true'],
        encoding='utf-8',
        input=orig_registry_code,
    )

    f = io.StringIO(registry_code)

    # 1. Parse the CheckCode enum
    while next(f).strip() != 'pub enum CheckCode {':
        pass

    checkcode_lines = []
    while (line := next(f).strip().rstrip(',')) != '}':
        checkcode_lines.append(line)

    # 2. Parse the CheckKind enum
    while next(f).strip() != 'pub enum CheckKind {':
        pass

    struct_defs = {}

    while (line := next(f).strip()) != '}':
        if line.startswith('//'):
            continue
        line = line.rstrip(',')
        line = re.sub(r'{', '{ pub ', line)
        line = re.sub(r'\(', '(pub ', line)
        line = re.sub(',', ', pub', line)
        kind = split_words(line)[1]
        struct_defs[kind] = 'pub struct ' + line + (';' * (line[-1] != '}'))

    # 3. parse the kind() impl for CheckKind
    while next(f).rstrip() != "    pub fn kind(&self) -> CheckKind {":
        pass
    assert next(f).strip() == 'match self {'

    placeholders = checkkind_match_arms(f)

    # 4. parse the CheckKind -> CheckCode mapping
    while next(f).strip() != "pub fn code(&self) -> &'static CheckCode {":
        pass
    assert next(f).strip() == 'match self {'

    kind2code = {}
    while (line := next(f).strip().rstrip(',')) != '}':
        if line.startswith('//'):
            continue
        parts = re.split(r'\b', line)
        kind2code[parts[3]] = parts[-2]

    code2kind = {code: kind for kind, code in kind2code.items()}

    # 5. parse the body() impl for CheckKind

    while next(f).rstrip() != "    pub fn body(&self) -> String {":
        pass
    assert next(f).strip() == 'match self {'

    bodies = checkkind_match_arms(f)

    # 6. find fixable
    always_fixable = []
    sometimes_fixable = []

    while next(f).strip() != "// Always-fixable checks.":
        pass

    while (line := next(f).strip()) != '// Conditionally-fixable checks.':
        always_fixable.append(split_words(line)[3])

    while (line := next(f).strip()) != '// Non-fixable checks.':
        sometimes_fixable.append(split_words(line)[3])

    # 7. find autofix message
    while next(f).rstrip() != indent + "pub fn commit(&self) -> Option<String> {":
        pass
    assert next(f).strip() == 'match self {'

    autofix_msg = checkkind_match_arms(f, strip_some=True)

reg = '''\
macro_rules! define_rule_mapping {
    ($($code:ident => $mod:ident::$name:ident,)+) => {
        // TODO: implement
    };
}

define_rule_mapping!(
'''
for line in checkcode_lines:
    if line.startswith('//'):
        reg += indent + line + '\n'
        continue
    code = line
    reg += indent + code + ' => violations::' + code2kind[code] + ',\n'
reg += ');\n\n'

with open('src/registry.rs', 'w') as f:
    marker = '#[derive'
    f.write(orig_registry_code.replace(marker, reg + marker, 1))

out = '''\
use itertools::Itertools;

use crate::define_violation;
use crate::flake8_debugger::types::DebuggerUsingType;
use crate::flake8_pytest_style::types::{ParametrizeNameType, ParametrizeValuesType, ParametrizeValuesRowType};
use crate::flake8_quotes::settings::Quote;
use crate::flake8_tidy_imports::settings::Strictness;
use crate::pyupgrade::types::Primitive;
use crate::registry::{
    Branch, DeferralKeyword, EqCmpop, IsCmpop, LiteralType, MockReference, UnusedCodes,
};
use crate::violation::{AlwaysAutofixableViolation, Violation};
'''

for line in checkcode_lines:
    if line.startswith('//'):
        out += '\n' + line + '\n\n'
        continue

    code = line
    kind = code2kind[code]
    out += 'define_violation!(' + struct_defs[kind] + ');\n'
    if kind in always_fixable:
        out += f'impl AlwaysAutofixableViolation for {kind} {{\n'
    else:
        out += f'impl Violation for {kind} {{\n'
    out += 'fn message(&self) -> String {'
    out += bodies[kind]
    out += '}'
    if kind in always_fixable:
        out += 'fn autofix_title(&self) -> String {'
        out += autofix_msg[kind]
        out += '}'
    elif kind in sometimes_fixable:
        out += 'fn autofix_title_formatter(&self) -> Option<fn(&Self) -> String> {'
        out += 'todo!()'
        out += '}'
    out += 'fn placeholder() -> Self {'
    out += placeholders[code].replace('CheckKind::', '')
    out += '}'
    out += '}\n\n'

with open('src/violations.rs', 'w') as f:
    f.write(out)

with open('src/lib.rs', 'r') as f:
    mod = f.read()
with open('src/lib.rs', 'w') as f:
    marker = 'mod violation;'
    f.write(mod.replace(marker, marker + '\nmod violations;'))
2023-01-07 15:14:58 -05:00
Martin Fischer
15084dff9d structs 1/9: Manually preprocess registry.rs 2023-01-07 15:14:58 -05:00
Martin Fischer
eea1379a74 structs 0/9: Introduce Violation trait
For every available rule registry.rs currently defines:

1. A CheckCode variant to identify the rule.
2. A CheckKind variant to represent violations of the rule.
3. A mapping from the CheckCode variant to a placeholder CheckKind instance.
4. A mapping from the CheckKind variant to CheckCode.
5. A mapping from the CheckKind to a string description.
6. A mapping from the CheckKind to a boolean indicating if autofix is available.
7. A mapping from the CheckKind to a string describing the autofix if available.

Since registry.rs defines all of this for every single rule and
ruff has hundreds of rules, this results in the lines specific to
a particular rule to be hundreds of lines apart, making the code
cumbersome to read and edit.

This commit introduces a new Violation trait so that the rule-specific
details of the above steps 5.-7. can be defined next to the rule
implementation. The idea is that once all CheckCode/CheckKind variants
have been converted to this new approach then the steps 1.-4. in
registry.rs could simply be generated via a declarative macro, e.g:

    define_rule_mapping!(
        E501 => pycodestyle::LineTooLong,
        ...
    );

(where `pycodestyle::LineTooLong` would be a struct that implements the
new Violation trait).

The define_rule_mapping! macro would then take care of generating the
CheckCode and CheckKind enums, as well as all of the implementations for
the previously mentioned mappings, by simply calling the methods of the
new Violation trait.

There is another nice benefit from this approach: We want to introduce
more thorough documentation for rules and we want the documentation of a
rule to be defined close by the implementation (so that it's easier to
check if they match and that they're less likely to become out of sync).
Since these new Violation structs can be defined close by the
implementation of a rule we can also use them as an anchor point for the
documentation of a rule by simply adding the documentation in the form
of a Rust doc comment to the struct.
2023-01-07 15:14:58 -05:00
Charlie Marsh
3e80c0d43e Fix clippy errors 2023-01-07 12:53:36 -05:00
Harutaka Kawamura
76a366e05a Trim trailing whitespace when extracting isort directives (#1715) 2023-01-07 12:39:31 -05:00
Harutaka Kawamura
07f72990a9 Implement autofix for PT009 (#1713) 2023-01-07 12:28:25 -05:00
messense
402feffe85 Implement flake8-simplify SIM103 (#1712)
Ref #998

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-01-07 07:33:24 -05:00
Harutaka Kawamura
5cdd7ccdb8 Use text in comment token (#1714)
https://github.com/RustPython/RustPython/pull/4426 has been merged. We
can simplify code using text in comment tokens.
2023-01-07 07:29:04 -05:00
Charlie Marsh
f1c3ebfe0f Bump version to 0.0.213 2023-01-07 00:30:56 -05:00
Charlie Marsh
c7e4e41a7a Revert "Include list of fixed files in stderr output (#1701)" (#1711)
This reverts commit 53ed52dc59.

I want to get some feedback on this before I send it out.
2023-01-07 00:30:25 -05:00
Charlie Marsh
311a823a4a Increase blackd wait time (#1709)
Resolves #1511.
2023-01-06 23:08:25 -05:00
Harutaka Kawamura
8c836aeecf Add more backticks to flake8-pytest-style error messages (#1707) 2023-01-06 22:55:24 -05:00
Charlie Marsh
3abd205f94 Lazily compute ranges for class and function bindings (#1708)
This has a fairly significant performance impact (~320ms to ~307ms on
the CPython benchmark).
2023-01-06 22:55:13 -05:00
Charlie Marsh
0527fb9335 Automatically remove unused variables (#1683)
Closes #1460.
2023-01-06 22:06:04 -05:00
Harutaka Kawamura
d5256f89b6 Use trim_end when checking line continutation (#1706)
Just a minor optimization.

Signed-off-by: harupy <hkawamura0130@gmail.com>
2023-01-06 21:59:35 -05:00
Charlie Marsh
3f84746d66 Remove add_check methods (#1705) 2023-01-06 21:58:21 -05:00
Anders Kaseorg
c39f687fca Switch SourceCodeGenerator.buffer from Vec<u8> to String (#1702)
This is the real issue underneath the `unsafe`/`unwrap` quandry in
#1677.

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-06 20:26:23 -05:00
Anders Kaseorg
dd35e724dd Forbid unsafe code (#1704)
We can reverse this later if it really becomes necessary, but I expect
safe Rust to be sufficient for all our needs.

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-06 20:25:59 -05:00
Anders Kaseorg
43599a9e78 Remove redundant #![allow()] from main_native (#1703)
`main_native.rs` is a module of `main.rs`, so the `#![allow()]`s in the
latter apply to the former automatically.

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-06 20:25:46 -05:00
Charlie Marsh
53ed52dc59 Include list of fixed files in stderr output (#1701)
This PR adds the list of fixed files to Ruff's output (send to `stderr`,
and omitted for `--silent` and `--quiet` settings):

![Screen Shot 2023-01-06 at 7 07 57
PM](https://user-images.githubusercontent.com/1309177/211120323-6203e624-b38d-47ae-a544-8d13e2410396.png)

Closes #1667.
2023-01-06 19:51:11 -05:00
Charlie Marsh
24999019e0 Include error location in GitHub Action diagnostic messages (#1696)
This ensures that if you look at the GitHub Actions _logs_, you see the
entire message, including the location:

![Screen Shot 2023-01-06 at 3 08 06
PM](https://user-images.githubusercontent.com/1309177/211091772-df6f1deb-c741-435c-be2e-6ee22347a073.png)

The downside is that the location gets repeated inline:

![Screen Shot 2023-01-06 at 3 08 30
PM](https://user-images.githubusercontent.com/1309177/211091800-57020736-95fa-4e41-acb3-eb11c848ba7e.png)

See: #1693.
2023-01-06 15:58:16 -05:00
Charlie Marsh
12d2526edb Require explicit opt-in for GitHub and Gitlab formats (#1697) 2023-01-06 15:57:56 -05:00
Charlie Marsh
81b812d94c Delete unreferenced snapshot 2023-01-06 15:56:47 -05:00
Maksudul Haque
9409b49ea2 [flake8-bandit] Add Rule for S501 (request call with verify=False) (#1695)
ref: https://github.com/charliermarsh/ruff/issues/1646
2023-01-06 11:44:19 -05:00
Chammika Mannakkara
1392170dbf Simplify SIM201, SIM202, SIM208 (#1666)
Flake8 simplify #998 

SIM201, SIM202 and SIM208 is done here with fixes.

Note: SIM203 == E713 

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-01-06 10:47:48 -05:00
messense
0a940b3cb4 Implement flake8-simplify SIM109 (#1687)
Ref #998

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-01-06 10:29:49 -05:00
Maksudul Haque
6aba43a9b0 [flake8-bandit] Add Rule for S113 (requests call without timeout) (#1692)
ref: https://github.com/charliermarsh/ruff/issues/1646

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-01-06 10:26:08 -05:00
Charlie Marsh
8a3a6a901a Avoiding flagging elif statements as potential ternaries (#1694) 2023-01-06 10:20:45 -05:00
Charlie Marsh
18a301a214 Add specialized conversions for RefEquality (#1689) 2023-01-06 10:02:17 -05:00
Harutaka Kawamura
53157bc634 Remove TODO comment (#1691) 2023-01-06 10:02:07 -05:00
messense
76a9dc61f0 Implement flake8-simplify SIM108 (#1684)
Ref #998

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-01-06 08:28:51 -05:00
Maksudul Haque
16d7e13c72 Update CONTRIBUTING.md location on README.md (#1688) 2023-01-06 08:05:24 -05:00
Charlie Marsh
5ed58ae595 Add requested context to issue template (#1679) 2023-01-06 07:29:08 -05:00
Charlie Marsh
cecd4b166c Don't mark D205 as fixable in more-lines case (#1682)
Closes #1672.
2023-01-05 23:20:14 -05:00
Charlie Marsh
4ddcdd02d6 Tweak badge logo (#1681) 2023-01-05 23:07:21 -05:00
messense
43575da537 Replace toml with toml_edit (#1680)
The `toml` crate doesn't support TOML 1.0, but `toml_edit` does. While
there is a plan to [migrate `toml` to be on
`toml_edit`](https://github.com/toml-rs/toml/issues/340), it's not ready
yet and it's very easy to switch back to `toml` when it's ready.
2023-01-05 22:08:23 -05:00
Charlie Marsh
fe67a0d239 Implement From conversion for style detector-to-generator (#1678) 2023-01-05 21:47:48 -05:00
Charlie Marsh
8caa73df6a Remove Result from SourceCodeGenerator signature (#1677)
We populate this buffer ourselves, so I believe it's fine for us to use
an unchecked UTF-8 cast here. It _dramatically_ simplifies so much
downstream code.
2023-01-05 21:41:26 -05:00
Charlie Marsh
ee4cae97d5 Bump version to 0.0.212 2023-01-05 21:25:42 -05:00
Anders Kaseorg
2e3787adff Remove an unneeded .to_string() in tokenize_files_to_codes_mapping (#1676)
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-05 20:56:11 -05:00
Anders Kaseorg
81b211d1b7 Simplify Option<String> → Option<&str> conversion using as_deref (#1675)
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-05 20:55:59 -05:00
Anders Kaseorg
1ad72261f1 Replace &String with &str in AnnotatedImport::ImportFrom (#1674)
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2023-01-05 20:55:46 -05:00
Charlie Marsh
914287d31b Fix format and lint errors 2023-01-05 20:30:01 -05:00
Charlie Marsh
75bb6ad456 Implement duplicate isinstance detection (SIM101) (#1673)
See: #998.
2023-01-05 20:21:40 -05:00
Charlie Marsh
04111da3f3 Improve Pandas call and attribute detection (#1671)
This PR adds some guardrails to avoid common false positives in our
`pandas-vet` rules. Specifically, we now avoid triggering `pandas-vet`
rules if the target of the call or attribute (i.e., the `x` in
`x.stack(...)`) is unbound, or bound to something that couldn't be a
DataFrame (like an import that _isn't_ `pandas`, or a class definition).
This lets us avoid common false positives like `np.stack(...)`.

Resolves #1659.
2023-01-05 19:30:54 -05:00
Charlie Marsh
2464cf6fe9 Fix some &String, &Option, and &Vec usages (#1670) 2023-01-05 18:56:03 -05:00
Charlie Marsh
d34e6c02a1 Allow overhang in Google-style docstring arguments (#1668)
Resolves #1662.
2023-01-05 14:36:19 -05:00
Diego Palacios
e6611c4830 Fix flake8-import-conventions configuration examples (#1660) 2023-01-05 13:37:25 -05:00
Maksudul Haque
2d23b1ae69 [flake8-bandit] Add Rule for S506 (unsafe use of yaml load) (#1664)
See: https://github.com/charliermarsh/ruff/issues/1646.

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-01-05 13:35:01 -05:00
Charlie Marsh
5eb03d5e09 Avoid false-positives for yields with non-identical references (#1665)
Resolves #1663.
2023-01-05 12:14:15 -05:00
Maksudul Haque
9f8ef1737e [flake8-bandit] Add Rule for S324 (Insecure hash functions in hashlib) (#1661)
ref: https://github.com/charliermarsh/ruff/issues/1646
2023-01-05 11:45:47 -05:00
messense
1991d618a3 Add proc-macro to derive CheckCodePrefix (#1656)
IMO a derive macro is a natural way to generate new code, and it reduces
the chance of merge conflicts.
2023-01-05 11:39:16 -05:00
Martin Fischer
2045b739a9 Stop highlighting --help output in README as shell (#1655)
This PR is meant to address the following obviously unintended GitHub
rendering:

![image](https://user-images.githubusercontent.com/73739153/210713719-7fb465b1-db91-4074-8a0c-4efa3c47c2f4.png)
2023-01-05 09:46:49 -05:00
Martin Fischer
53e3dd8548 Add ignore-overlong-task-comments setting
Imagine a .py file containing the following comment:

    # TODO: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed
    # do eiusmod tempor incididunt ut labore et dolore magna aliqua.

Since `git grep` only matches individual lines `git grep TODO` would
only output the first line of the comment, cutting off potentially
important information. (git grep currently doesn't support multiline
grepping). Projects using such a workflow therefore probably format
the comment in a single line instead:

    # TODO: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

This commit introduces a setting to accomdate this workflow by making
the line-length checks (`E501`) optionally ignore overlong lines
if they start with a recognized task tag.

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-01-04 23:54:50 -05:00
Martin Fischer
78c9056173 Add pycodestyle::settings
This step is split up into a separate commit so
that the following commit has a cleaner diff.
2023-01-04 23:54:50 -05:00
Martin Fischer
8d56e412ef Add task-tags setting
Programmers often leave comments to themselves and others such as:

    # TODO: Use a faster algorithm?

The keywords used to prefix such comments are just a convention and vary
from project to project. Other common keywords include FIXME and HACK.

The keywords in use for the codebase are of interest to ruff because
ruff does also lint comments. For example the ERA lint detects
commented-out code but ignores comments starting with such a keyword.
Previously the ERA lint simply hardcoded the regular expression
TODO|FIXME|XXX to achieve that. This commit introduces a new `task-tags`
setting to make this configurable (and to allow other comment lints to
recognize the same set of keywords).

The term "task tags" has probably been popularized by the Eclipse
IDE.[1] For Python there has been the proposal PEP 350[2], which
referred to such keywords as "codetags". That proposal however has been
rejected. We are choosing the term "task tags" over "code tags" because
the former is more descriptive: a task tag describes a task.

While according to the PEP 350 such keywords are also sometimes used for
non-tasks e.g. NOBUG to describe a well-known problem that will never be
addressed due to design problems or domain limitations, such keywords
are so rare that we are neglecting them here in favor of more
descriptive terminology. The vast majority of such keywords does
describe tasks, so naming the setting "task-tags" is apt.

[1]: https://www.eclipse.org/pdt/help/html/task_tags.htm
[2]: https://peps.python.org/pep-0350/

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2023-01-04 23:54:50 -05:00
Charlie Marsh
3400be18a6 Revert "Add task-tags & ignore-overlong-task-comments settings (#1550)"
This reverts commit ca48492137.
2023-01-04 23:54:50 -05:00
Charlie Marsh
7b59cd2d32 Bump version to 0.0.211 2023-01-04 23:13:04 -05:00
Charlie Marsh
b8ed4d402a Implement SIM110 and SIM111 (conversion to any and all) (#1653) 2023-01-04 23:08:12 -05:00
messense
46dcf3c4c0 Implement flake8-simplify SIM107 (#1650) 2023-01-04 23:02:25 -05:00
Charlie Marsh
ef7777703b Run generation steps 2023-01-04 22:05:04 -05:00
messense
6a1edeb694 Cancel outdated in-progress workflow automatically (#1652) 2023-01-04 22:03:26 -05:00
Charlie Marsh
fb8024a6ac Implement nested with detection (SIM117) (#1651) 2023-01-04 21:22:25 -05:00
Edgar R. M
2f71bdfbfc Implement flake8-bandit rule S108 (#1644) 2023-01-04 21:11:13 -05:00
Charlie Marsh
30d6688c26 Implement nested-if detection (#1649) 2023-01-04 20:55:01 -05:00
Charlie Marsh
9041423b92 Move external licenses to separate directory (#1648) 2023-01-04 20:07:51 -05:00
Charlie Marsh
c91c435dc9 Fix URL in pyproject.toml 2023-01-04 19:23:40 -05:00
Charlie Marsh
5cb162bd7b Add missing McCabe comment 2023-01-04 19:16:36 -05:00
Charlie Marsh
7339d7eccf Implement builtin import removal (#1645) 2023-01-04 19:10:16 -05:00
Charlie Marsh
2ff816f108 DRY up unused import removal code (#1643) 2023-01-04 19:03:52 -05:00
Charlie Marsh
980d10b952 Add Ruff badge to README (#1642) 2023-01-04 17:27:01 -05:00
Charlie Marsh
6c5db1008d Add badge JSON (#1641) 2023-01-04 17:24:27 -05:00
Martin Fischer
ca48492137 Add task-tags & ignore-overlong-task-comments settings (#1550) 2023-01-04 17:10:21 -05:00
Charlie Marsh
7c23701b62 Note a few more incompatibilities (#1639) 2023-01-04 16:05:15 -05:00
Charlie Marsh
8da2c4815a Tweak Yoda condition message (#1638) 2023-01-04 15:58:01 -05:00
Charlie Marsh
34fec8cbd0 Rename flake8-bandit rules from plugins to checks (#1637) 2023-01-04 15:49:05 -05:00
Edgar R. M
1817f8752b Implement flake8-bandit rule S103 (#1636) 2023-01-04 15:47:38 -05:00
Colin Delahunty
8b8e6e44ea Adding my company to the "used in" category of the Readme. (#1631) 2023-01-04 12:31:18 -05:00
Harutaka Kawamura
12166584c4 Minor fixes for SIM105 (#1633) 2023-01-04 11:01:06 -05:00
Charlie Marsh
9ede902328 Run generate-all 2023-01-04 10:46:24 -05:00
messense
0df28bdd4e Implement flake8-simplify SIM105 rule (#1621) 2023-01-04 08:10:59 -05:00
Charlie Marsh
8b07f9517a Implement SIM220 and SIM221 (#1630) 2023-01-04 08:07:00 -05:00
Harutaka Kawamura
0a0e1926f2 Check SIM118 in comprehension (#1627) 2023-01-04 07:05:13 -05:00
Charlie Marsh
4473c7e905 Update stale references in CONTRIBUTING.md 2023-01-03 23:44:10 -05:00
Charlie Marsh
20930b3675 Add some more users to the README (#1623) 2023-01-03 23:06:08 -05:00
Colin Delahunty
fb1a638a96 Implement yield-to-yield from conversion (#1544) 2023-01-03 22:56:52 -05:00
Edgar R. M
16964409a8 Implement missing fixes for PT006 (#1622) 2023-01-03 22:52:51 -05:00
Charlie Marsh
aacfc9ee0b Bump version to 0.0.210 2023-01-03 21:46:08 -05:00
Charlie Marsh
bd14f92898 Avoid byte-string conversions (#1618) 2023-01-03 21:45:14 -05:00
Charlie Marsh
cc116b0192 Treat convention as setting ignore, rather than select (#1611) 2023-01-03 21:27:53 -05:00
Charlie Marsh
0d27c0be27 Treat .pyi files as __future__ annotations-enabled (#1616) 2023-01-03 21:27:26 -05:00
Edgar R. M
60359c6adf Fix leftover whitespace when removing pass for PIE790 (#1612) 2023-01-03 20:44:59 -05:00
Charlie Marsh
77692e4b5f Associate inline comments with parenthesized ImportFrom statements (#1609) 2023-01-03 20:02:12 -05:00
Charlie Marsh
731f3a74a9 Fix *arg and **kwarg handling for Google docstrings (#1608) 2023-01-03 18:17:42 -05:00
Matt Oberle
03275c9c98 Add isort.order-by-type boolean setting (#1607) 2023-01-03 18:07:44 -05:00
Harutaka Kawamura
8d99e317b8 Implement autofix for PT022 (#1604) 2023-01-03 13:36:28 -05:00
Maksudul Haque
d4d67e3014 Do not Change Quotation Style for PT006 Autofix (#1600) 2023-01-03 10:16:49 -05:00
Charlie Marsh
e9a236f740 Bump version to 0.0.209 2023-01-03 08:27:28 -05:00
Ran Benita
ebb31dc29b Fix PT006 autofix of parametrize name strings like ' first, , second ' (#1591) 2023-01-03 08:12:09 -05:00
Charlie Marsh
b9e92affb1 Avoid silently dropping code generator errors (#1598) 2023-01-03 08:11:18 -05:00
Charlie Marsh
68fbd0f029 Preserve style when generating flake8-simplify messages (#1599) 2023-01-03 08:05:55 -05:00
Charlie Marsh
8d01efb571 Avoid hard unwrap in PT checks (#1597) 2023-01-03 07:39:52 -05:00
Pedram Navid
da5a25b421 Add autofix for SIM300 (#1588) 2023-01-03 07:19:04 -05:00
Charlie Marsh
bfdab4ac94 Add flake8-pytest-style settings to hash (#1595) 2023-01-03 07:12:33 -05:00
jvstme
d1389894a4 Fix several typos in README (#1590) 2023-01-03 07:06:43 -05:00
Charlie Marsh
8b277138de Bump version to 0.0.208 2023-01-02 23:19:03 -05:00
Charlie Marsh
e0fe34c523 Implement and-false and or-true rules (#1586) 2023-01-02 23:10:42 -05:00
Charlie Marsh
995fee5ddd Increment flake8-pie implementation count 2023-01-02 22:47:05 -05:00
Charlie Marsh
99906c16db Prefer GitHub icon on mobile (#1585) 2023-01-02 22:46:23 -05:00
Charlie Marsh
b6cb35414e Swap accent color for playground (#1584) 2023-01-02 22:44:09 -05:00
Harutaka Kawamura
b351221049 Mark FStringMissingPlaceholders as fixable (#1582) 2023-01-02 22:41:40 -05:00
Charlie Marsh
afb6f55b8d Add a link to GitHub from the playground (#1583) 2023-01-02 22:40:38 -05:00
Harutaka Kawamura
03a8ece954 Implement autofix for F541 (#1577) 2023-01-02 22:28:32 -05:00
Charlie Marsh
8aeec35bfb Implement dupe-class-field-definitions (#1581) 2023-01-02 22:26:01 -05:00
Charlie Marsh
93259acb31 Implement unnecessary-pass-statement (#1580) 2023-01-02 22:15:24 -05:00
Charlie Marsh
ca7fe686d5 Add scripts to generate plugin and check boilerplate (#1579) 2023-01-02 22:10:31 -05:00
Charlie Marsh
5dd9e99a4b Add flake8-pie plugin with prefer_list_builtin (#1578) 2023-01-02 21:47:38 -05:00
Charlie Marsh
8f0270acfe Remove registry_gen.rs at root 2023-01-02 21:31:19 -05:00
Charlie Marsh
7ce38840a2 Re-run registry_gen.rs generation 2023-01-02 21:29:53 -05:00
Charlie Marsh
8ab8217ca5 Fix destination for registry_gen.rs 2023-01-02 21:29:08 -05:00
Charlie Marsh
5d3ff69053 Add comment annotations to plugin match 2023-01-02 20:49:30 -05:00
Charlie Marsh
726399b2b3 Move Ruff checks to the end of each list 2023-01-02 20:44:27 -05:00
Charlie Marsh
8329237f19 Warn user when D203 and D211 are enabled (#1576) 2023-01-02 19:54:55 -05:00
Oliver Margetts
cd5882c66d Remove need for vendored format/cformat code (#1573) 2023-01-02 19:37:31 -05:00
Charlie Marsh
0c05488740 Automatically set baseline D codes based on convention (#1574) 2023-01-02 19:08:56 -05:00
Charlie Marsh
1425b21d93 Avoid invalid trailing comma fixes for mock rewrites (#1570) 2023-01-02 18:03:43 -05:00
Charlie Marsh
e5a59f41b0 Remove extend- from docstring configuration examples (#1571) 2023-01-02 17:53:41 -05:00
Charlie Marsh
8647bec3cb Rename checks.rs to registry.rs (#1566) 2023-01-02 17:26:51 -05:00
Charlie Marsh
14042800c2 Remove common-path dependency (#1565) 2023-01-02 17:23:29 -05:00
Charlie Marsh
21986e89fd Always check directly-passed-in files (#1564) 2023-01-02 16:49:44 -05:00
Edgar R. M
c4014ef2d3 Implement flake8-pytest-style (#1506) 2023-01-02 16:34:17 -05:00
Charlie Marsh
9ffd20707f Avoid PEP 604 rewrites for runtime annotations (#1563) 2023-01-02 16:33:52 -05:00
Charlie Marsh
6d5aa344a1 Avoid merging import from statements with inline comments (#1562) 2023-01-02 16:24:41 -05:00
Colin Delahunty
e9be5fc7be Add typo linter (#1553) 2023-01-02 15:57:59 -05:00
Charlie Marsh
f74050e5b1 Bump version to 0.0.207 2023-01-02 14:39:32 -05:00
Martin Fischer
90b2d85c85 Fix __init__.py being private (#1556)
Previously visibility::module_visibility() returned Private
for any module name starting with an underscore, resulting in
__init__.py being categorized as private, which in turn resulted
in D104 (Missing docstring in public package) never being reported
for __init__.py files.
2023-01-02 14:39:23 -05:00
Charlie Marsh
ccf848705d Detect unpacking assignments in eradicate (#1559) 2023-01-02 14:05:58 -05:00
Charlie Marsh
3b535fcc74 Add explicit new-rule recommendation in CONTRIBUTING.md (#1558) 2023-01-02 13:50:11 -05:00
Víctor
06321fd240 Add usage clarification to README (#1557) 2023-01-02 13:40:16 -05:00
Martin Fischer
cdae2f0e67 Fix typing::match_annotated_subscript matching ExprKind::Call (#1554) 2023-01-02 12:13:45 -05:00
Martin Fischer
f52691a90a Print warning when running debug builds without --no-cache (#1549) 2023-01-02 12:12:04 -05:00
Pedram Navid
07e47bef4b Add flake8-simplify SIM300 check for Yoda Conditions (#1539) 2023-01-01 18:37:40 -05:00
Anders Kaseorg
86b61806a5 Correct UP027 message to “generator expression” (#1540) 2023-01-01 18:30:58 -05:00
Charlie Marsh
31ce37dd8e Avoid PD false positives on some non-DataFrame expressions (#1538) 2023-01-01 17:05:57 -05:00
Charlie Marsh
2cf6d05586 Avoid triggering PD errors on method calls (#1537) 2023-01-01 17:00:17 -05:00
Colin Delahunty
65c34c56d6 Implement list-to-tuple comprehension unpacking (#1534) 2023-01-01 16:53:26 -05:00
Charlie Marsh
2315db7d13 Bump version to 0.0.206 2023-01-01 16:39:29 -05:00
Charlie Marsh
f1a183c171 Rewrite mock.mock attribute accesses (#1533) 2023-01-01 13:14:09 -05:00
Harutaka Kawamura
509c6d5ec7 Add visit_format_spec to avoid false positives for F541 in f-string format specifier (#1528) 2023-01-01 13:03:32 -05:00
Maksudul Haque
6695988b59 Do not Change Quotation Style for SIM118 Autofix (#1529) 2023-01-01 12:53:46 -05:00
Harutaka Kawamura
e3867b172d Simplify unused snapshot check (#1525) 2023-01-01 02:43:07 -05:00
Harutaka Kawamura
4b8e30f350 Fix Name node range in NamedExpr node (#1526) 2023-01-01 02:41:49 -05:00
Charlie Marsh
8fd0d8e9d8 Bump pyupgrade implementation count 2022-12-31 21:25:34 -05:00
Colin Delahunty
70895a8f1e Pyupgrade: import mock to from unittest import mock (#1488) 2022-12-31 21:25:06 -05:00
Charlie Marsh
f2c9f94f73 Avoid some false positives for ends-in-period checks (#1521) 2022-12-31 18:38:22 -05:00
Charlie Marsh
605c6069e2 Ignore property assignments in RET504 (#1520) 2022-12-31 18:04:13 -05:00
Charlie Marsh
92c2981b6d Add dark mode variant for benchmark image (#1519) 2022-12-31 17:47:32 -05:00
Colin Delahunty
4ad8db3d61 Pyupgrade: Turn errors into OSError (#1434) 2022-12-31 16:36:05 -05:00
Charlie Marsh
0e8c237167 Bump version to 0.0.205 2022-12-31 13:44:39 -05:00
Harutaka Kawamura
960c5e2006 Use more precise error ranges for names (#1513) 2022-12-31 13:42:39 -05:00
Charlie Marsh
9ba17fbf92 Avoid flagging nested f-strings (#1516) 2022-12-31 13:41:21 -05:00
Charlie Marsh
bfdf972a5d Add code kind to Quick Fix action 2022-12-31 10:26:47 -05:00
Charlie Marsh
0c215365ae Bump version to 0.0.204 2022-12-31 08:20:09 -05:00
Maksudul Haque
815284f890 Check for Unsupported Files and Display Errors and Warnings (#1509) 2022-12-31 08:12:55 -05:00
Charlie Marsh
6880338a9a Restore pyproject.toml 2022-12-31 08:06:08 -05:00
Charlie Marsh
68b749c67d Remove foo directory 2022-12-31 08:05:04 -05:00
Reiner Gerecke
c0fc55b812 Generate source code with detected line ending (#1487) 2022-12-31 08:02:29 -05:00
Reiner Gerecke
ba9cf70917 Adjust test_path helper to detect round-trip autofix issues (#1501) 2022-12-31 08:02:13 -05:00
Harutaka Kawamura
f73dfbbfd3 Fix E722 and F707 ranges (#1508) 2022-12-31 07:58:46 -05:00
Reiner Gerecke
62c273cd22 Include fix commit message when showing violations together with source (#1505) 2022-12-31 07:54:41 -05:00
Harutaka Kawamura
938ad9a39e Fix N818 range (#1503) 2022-12-31 07:43:03 -05:00
Harutaka Kawamura
14248cb8cb Improve PLW0120 range (#1500) 2022-12-31 07:42:49 -05:00
Harutaka Kawamura
3a280039e1 Improve F811 range for function and class definitions (#1499) 2022-12-31 07:42:18 -05:00
Harutaka Kawamura
4e9e58bdc0 Improve T20X ranges (#1502) 2022-12-31 07:41:53 -05:00
Harutaka Kawamura
926b5494ad Remove unused snapshots (#1497) 2022-12-31 07:40:38 -05:00
Reiner Gerecke
6717b48ca5 Fix detection of changed imports in isort plugin (#1504) 2022-12-31 07:37:27 -05:00
Harutaka Kawamura
f7bb5bc858 Remove F831 (#1495) 2022-12-30 23:57:51 -05:00
Harutaka Kawamura
3e23fd1487 Stop overriding locations for expressions within f-strings (#1494) 2022-12-30 23:43:59 -05:00
Charlie Marsh
01c74e0629 Add a "fix message" to every autofix-able check (#1489) 2022-12-30 23:16:03 -05:00
Charlie Marsh
1e3cf87f67 Escape strings when formatting check messages (#1493) 2022-12-30 22:11:01 -05:00
Charlie Marsh
248447e139 Trim CLI help during generation (#1492) 2022-12-30 22:03:58 -05:00
Charlie Marsh
95f139583a Modify pyproject.toml to meet schema compliance 2022-12-30 15:51:35 -05:00
Charlie Marsh
74903f23d6 Bump version to 0.0.203 2022-12-30 15:33:30 -05:00
Charlie Marsh
3ee20a70d3 Remove lingering ruff_options.ts references 2022-12-30 15:33:09 -05:00
Charlie Marsh
4c2fbb7ac0 Remove hidden autoformat command (#1486) 2022-12-30 15:32:05 -05:00
Charlie Marsh
7a66f98590 Move some argument validation into Clap (#1485) 2022-12-30 15:29:41 -05:00
Charlie Marsh
a2bf3916f3 Make clean a standalone command 2022-12-30 15:20:18 -05:00
Reiner Gerecke
c9aa7b9308 Generate the README's --help output automatically via cargo +nightly dev generate-all (#1483) 2022-12-30 15:06:32 -05:00
Charlie Marsh
d880ca6cc6 Add a command to clear the Ruff cache (#1484) 2022-12-30 13:52:16 -05:00
Reiner Gerecke
080f99b908 Detect line endings and use them during code generation (#1482) 2022-12-30 12:59:40 -05:00
Charlie Marsh
a7dc491ff1 Fix clippy 2022-12-30 12:34:43 -05:00
Charlie Marsh
cdc8f8c91a Remove support for ur prefixes (#1481) 2022-12-30 11:21:05 -05:00
Colin Delahunty
138c46e793 Simplified code for unicode fix (#1475) 2022-12-30 11:18:52 -05:00
Charlie Marsh
a86c57a832 Support multi-line noqa directives for 'import from' (#1479) 2022-12-30 11:16:50 -05:00
Charlie Marsh
818582fe8a Bump version to 0.0.202 2022-12-30 08:16:32 -05:00
Charlie Marsh
90574c1088 Set editor background on top-level component (#1478) 2022-12-30 07:55:54 -05:00
Charlie Marsh
3061a35e7c Use more precise ranges for class and function checks (#1476) 2022-12-30 07:39:20 -05:00
Martin Fischer
87681697ae Improve CLI help for --select (#1471) 2022-12-30 07:16:44 -05:00
Martin Fischer
e9ec2a7b36 Add use test_case::test_case; to CONTRIBUTING.md
I previously tried adding the #[test_case()] attribute macro and got
confused because the Rust compilation suddenly failed with:

    error[E0658]: use of unstable library feature 'custom_test_frameworks': custom test frameworks are an unstable feature

which is a quite confusing error message.  The solution is to just add
`use test_case::test_case;`, so this commit adds that line to the
example in CONTRIBUTING.md to spare others this source of confusion.
2022-12-30 07:13:48 -05:00
Martin Fischer
b0bb75dc1c Add --select to command suggested in CONTRIBUTING.md
By default only E* and F* lints are enabled. I previously followed the
CONTRIBUTING.md instructions to implement a TID* lint and was confused
why my lint wasn't being run.
2022-12-30 07:13:48 -05:00
Martin Fischer
ebca5c2df8 Make banned-api config setting optional (#1465) 2022-12-30 07:09:56 -05:00
Charlie Marsh
16b10c42f0 Fix lint issues 2022-12-29 23:12:28 -05:00
Charlie Marsh
4a6e5d1549 Bump version to 0.0.201 2022-12-29 23:01:35 -05:00
Charlie Marsh
b078050732 Implicit flake8-implicit-str-concat (#1463) 2022-12-29 23:00:55 -05:00
Charlie Marsh
5f796b39b4 Run cargo fmt 2022-12-29 22:25:14 -05:00
Martin Fischer
9d34da23bd Implement TID251 (banning modules & module members) (#1436) 2022-12-29 22:11:12 -05:00
Charlie Marsh
bde12c3bb3 Restore quick fixes for playground 2022-12-29 20:16:19 -05:00
Colin Delahunty
f735660801 Removed unicode literals (#1448) 2022-12-29 20:11:33 -05:00
Charlie Marsh
34cd22dfc1 Copy URL but don't update the hash (#1458) 2022-12-29 19:46:50 -05:00
Charlie Marsh
9fafe16a55 Re-add GitHub badge to the bottom of the page 2022-12-29 19:38:33 -05:00
Charlie Marsh
e9a4cb1c1d Remove generated TypeScript options (#1456) 2022-12-29 19:37:49 -05:00
Charlie Marsh
9db825c731 Use trailingComma: 'all' (#1457) 2022-12-29 19:36:51 -05:00
Charlie Marsh
2c7464604a Implement dark mode (#1455) 2022-12-29 19:33:46 -05:00
Charlie Marsh
cd2099f772 Move default options into WASM interface (#1453) 2022-12-29 18:06:57 -05:00
Adam Turner
091d36cd30 Add Sphinx to user list (#1451) 2022-12-29 18:06:09 -05:00
Mathieu Kniewallner
02f156c6cb docs(README): add missing flake8-simplify (#1449) 2022-12-29 17:02:26 -05:00
Charlie Marsh
9f7350961e Rename config to settings in the playground (#1450) 2022-12-29 16:59:38 -05:00
Charlie Marsh
118a93260a Bump version to 0.0.200 2022-12-29 13:31:23 -05:00
Charlie Marsh
1c16255884 Include docstrings for settings enum members (#1446) 2022-12-29 13:15:44 -05:00
Charlie Marsh
16c4552946 Update snapshots 2022-12-29 13:13:43 -05:00
Charlie Marsh
0ba3989b3d Make update check enablement cofnigurable (#1445) 2022-12-29 13:06:22 -05:00
Charlie Marsh
3435e15cba Avoid caching diffs (#1441) 2022-12-29 12:51:58 -05:00
Maksudul Haque
781bbbc286 [pygrep-hooks] Adds Check for Blanket # noqa (#1440) 2022-12-29 12:43:16 -05:00
Charlie Marsh
acf0b82f19 Re-style the Ruff playground (#1438) 2022-12-29 11:47:27 -05:00
Charlie Marsh
057414ddd4 Bump version to 0.0.199 2022-12-28 20:58:43 -05:00
Charlie Marsh
ca94e9aa26 Warn the user when max iteration count is reached (#1433) 2022-12-28 20:56:43 -05:00
Charlie Marsh
797b5bd261 Split into lint and lint-and-fix methods (#1432) 2022-12-28 20:14:33 -05:00
Charlie Marsh
a64f62f439 Revert setup.py change 2022-12-28 19:34:20 -05:00
Charlie Marsh
058ee8e6bf Add a --diff flag to dry-run autofixes (#1431) 2022-12-28 19:21:29 -05:00
Charlie Marsh
39fc1f0c1b Add a note on autofix settings 2022-12-28 17:26:38 -05:00
Colin Delahunty
34842b4c4b PyUpgrade: Replace pipes with capture_output=True (#1415) 2022-12-28 16:53:35 -05:00
Charlie Marsh
dfa6fa8f83 Check in updated snapshots 2022-12-28 16:42:55 -05:00
Colin Delahunty
6131c819ed Rewrite xml.etree.cElementTree to xml.etree.ElementTree (#1426) 2022-12-28 16:30:36 -05:00
Hannes Käufler
79ba420faa Extract duplicated logic into method (#1428) 2022-12-28 16:10:53 -05:00
Charlie Marsh
d16ba890ae Turn off wasm-pack tests (#1427) 2022-12-28 12:55:25 -05:00
Charlie Marsh
6b6851bf1f Update JSON schema 2022-12-28 12:27:01 -05:00
Charlie Marsh
056718ce75 Remove stray Plugins doc 2022-12-28 12:24:48 -05:00
Charlie Marsh
4521fdf021 Only test --lib for wasm-pack 2022-12-28 10:28:40 -05:00
Maksudul Haque
8e479628f2 Add Support for GitLab CI Code Quality Report Format (#1424) 2022-12-28 10:10:43 -05:00
Charlie Marsh
2a11c4b1f1 Try increasing wasm-bindgen timeout 2022-12-28 07:39:23 -05:00
Anders Kaseorg
a8cde5a936 Check for keyword arguments before the last star argument (#1420) 2022-12-27 23:20:03 -05:00
Charlie Marsh
1822b57ed5 Remove 'static 2022-12-27 21:57:32 -05:00
Charlie Marsh
c679570041 Bump version to 0.0.198 2022-12-27 21:39:53 -05:00
Charlie Marsh
edcb3a7217 Support --select ALL to enable all error codes (#1418) 2022-12-27 21:38:26 -05:00
Charlie Marsh
6e43dc7270 Add nbQA support to the docs (#1417) 2022-12-27 21:24:07 -05:00
Charlie Marsh
570d0864f2 Add rule to detect keyword arguments before starred arguments (#1416) 2022-12-27 21:17:22 -05:00
Charlie Marsh
d22e96916c Automatically detect and respect indentation and quotation code style (#1413) 2022-12-27 19:45:50 -05:00
Charlie Marsh
043d31dcdf Bump version to 0.0.197 2022-12-27 17:05:15 -05:00
Charlie Marsh
1392e4cced Default to double quotes in code_gen.rs (#1412) 2022-12-27 16:17:49 -05:00
Charlie Marsh
59ee89a091 Fix it_converts_docstring_conventions test 2022-12-27 15:41:29 -05:00
Charlie Marsh
6a7c3728ee Set convention in flake8-to-ruff (#1410) 2022-12-27 13:51:24 -05:00
Charlie Marsh
0a60eb0aca Fix invalid reference to ruff_options.rs (#1409) 2022-12-27 12:12:28 -05:00
Charlie Marsh
3e96803033 Bump version to 0.0.196 2022-12-27 12:02:02 -05:00
Colin Delahunty
c59035139c Pyupgrade: converts universal_newlines to text in subprocess.run (#1403) 2022-12-27 12:01:27 -05:00
Charlie Marsh
7632d7eda7 Allow specification of explicit docstring convention (#1408) 2022-12-27 11:50:28 -05:00
Charlie Marsh
b4dbe62da0 Add cargo +nightly dev generate-all (#1404) 2022-12-27 10:07:18 -05:00
Harutaka Kawamura
9106d5338b Replace make_tokenize with make_tokenizer_located (#1405) 2022-12-27 10:07:03 -05:00
Reiner Gerecke
534d8d049c Support isort's force-single-line option (#1366) 2022-12-27 08:51:32 -05:00
Charlie Marsh
e692c4a2cc Tweak secret detection for playground releases (#1402) 2022-12-27 08:41:53 -05:00
Reiner Gerecke
e0b39fa63e Implement pyupgrade check for io.open alias (#1399) 2022-12-27 07:47:40 -05:00
Charlie Marsh
320a48977b Tweak README again 2022-12-26 21:17:18 -05:00
Charlie Marsh
0d05aaeb6e Add monorepo note 2022-12-26 21:00:14 -05:00
Charlie Marsh
1e4b1533ad Bump version to 0.0.195 2022-12-26 20:41:39 -05:00
Charlie Marsh
df4f5358f9 Bump pyupgrade implementation count 2022-12-26 19:56:12 -05:00
Colin Delahunty
58c383401c Replace typing.Text with str (#1391) 2022-12-26 19:55:41 -05:00
Charlie Marsh
018b9a2977 Only run playground release in main repo (#1396) 2022-12-26 19:45:04 -05:00
Charlie Marsh
658cb87ddd Enable Quick Fix in the playground (#1395) 2022-12-26 19:25:50 -05:00
Charlie Marsh
0d35087bc6 Choose a more interesting example snippet (#1394) 2022-12-26 15:19:17 -05:00
Charlie Marsh
b721125af9 Add badge to playground (#1393) 2022-12-26 15:13:55 -05:00
Charlie Marsh
20d6b21d77 Add ESLint, Prettier, and TypeScript checks (#1384) 2022-12-26 15:08:22 -05:00
Charlie Marsh
1a27992f47 Enable preview deployments for playground (#1383) 2022-12-26 14:52:13 -05:00
Charlie Marsh
89cebe1ce2 Update name of Playground job 2022-12-26 12:10:22 -05:00
Reiner Gerecke
bdb1505262 Web playground with WASM (#1279) 2022-12-26 12:09:17 -05:00
Charlie Marsh
8c018e8261 Add settings validation to lib.rs 2022-12-26 10:12:07 -05:00
Colin Delahunty
debd909b2c Magic Trailing Commas in isort (#1363) 2022-12-26 09:40:02 -05:00
Reiner Gerecke
fa54538bd1 Only re-associate inline comments during normalization when necessary (#1380) 2022-12-26 07:52:13 -05:00
Reiner Gerecke
939f738a71 Update rust python to handle files with BOM (#1379) 2022-12-26 07:03:13 -05:00
Charlie Marsh
b0f30bef8f Add support for ruff.toml (#1378) 2022-12-25 21:55:07 -05:00
Charlie Marsh
28c45eb2a3 Remove required versions from pyproject.toml 2022-12-25 20:21:01 -05:00
Charlie Marsh
4dc45912e8 Run cargo dev commands 2022-12-25 20:12:12 -05:00
Charlie Marsh
5ef8bff341 Bump version to 0.0.194 2022-12-25 19:54:45 -05:00
Charlie Marsh
2ab8f77223 Update command-line help text 2022-12-25 19:54:14 -05:00
Charlie Marsh
8b72f55a09 Add --required-version (#1376) 2022-12-25 19:53:50 -05:00
Charlie Marsh
19121219fb Avoid double-extending past the end when showing source (#1377) 2022-12-25 19:52:42 -05:00
Charlie Marsh
d9355c989a Add a --fix-only command-line and pyproject.toml option (#1375) 2022-12-25 18:49:56 -05:00
Charlie Marsh
ec80d1cd85 Respect natural ordering for imports (#1374) 2022-12-25 18:11:41 -05:00
Charlie Marsh
9bb470c7d4 Ignore unused arguments for @overload stubs (#1373) 2022-12-25 17:22:31 -05:00
Harutaka Kawamura
dca3fcd8d1 Improve excepthandler_name_range (#1368) 2022-12-25 00:12:12 -05:00
Harutaka Kawamura
10f75c9620 Fix F841 (UnusedVariable) range in except handler (#1367) 2022-12-24 22:55:55 -05:00
Charlie Marsh
cc2110449c Run cargo dev commands 2022-12-24 15:06:12 -05:00
Charlie Marsh
f6ca49e05f Bump version to 0.0.193 2022-12-24 14:56:26 -05:00
Charlie Marsh
9a7331b2e2 Annotate RUF100 messages with unmatched, disabled, and unknown codes (#1365) 2022-12-24 14:55:55 -05:00
Edgar R. M
4888afd423 Generate JSON schema for Ruff options (#1329) 2022-12-24 14:10:22 -05:00
Sawbez
0dc523b081 Add autofix for W605 [InvalidEscapeSequence] (#1361) 2022-12-24 13:46:28 -05:00
Harutaka Kawamura
63772e335d Fix B025 location (#1360) 2022-12-24 12:22:11 -05:00
Reiner Gerecke
7f4ff1e38f Fix false-positive in RET504 when referencing globals (#1358) 2022-12-24 12:02:57 -05:00
Reiner Gerecke
32ebc1d227 Don't trigger E721 when comparing with None (#1356) 2022-12-24 04:45:40 -05:00
Sawbez
4ded155dc0 Add autofix for W292 [NoNewLineAtEndOfFile] (#1354) 2022-12-23 23:14:17 -05:00
Harutaka Kawamura
201e1250de Update RustPython to use the correct BinOp location (#1355) 2022-12-23 22:58:39 -05:00
Reiner Gerecke
102b049a32 Add cache-dir to command-line and pyproject.toml (#1351) 2022-12-23 22:58:29 -05:00
Charlie Marsh
74f49eda64 Bump compatibility to 3.11 (#1352) 2022-12-23 12:12:11 -05:00
Reiner Gerecke
9da3e2cca1 Implement "native literals" check from pyupgrade (#1350) 2022-12-23 11:40:32 -05:00
Charlie Marsh
e290050821 Avoid enabling all EM checks at once (#1349) 2022-12-23 08:25:07 -05:00
Charlie Marsh
bc9ed0a4ef Tweak LSP docs 2022-12-22 22:16:32 -05:00
Charlie Marsh
20b9b44973 Link to ruff-lsp docs 2022-12-22 21:53:11 -05:00
Charlie Marsh
6e5a553235 Update Neovim instructions 2022-12-22 21:52:30 -05:00
Charlie Marsh
2a08a63f17 Add a link to the PyCharm plugin (#1345) 2022-12-22 21:50:24 -05:00
Colin Delahunty
d4290e6721 Update CONTRIBUTING.md (#1344) 2022-12-22 21:04:19 -05:00
Charlie Marsh
51bda28a7d Bump version to 0.0.192 2022-12-22 17:31:31 -05:00
Reiner Gerecke
cc26051b7a Implement "datetime.UTC alias" check from pyupgrade (#1341) 2022-12-22 17:21:36 -05:00
Charlie Marsh
3ac5a9aa31 Respect --force-exclude for files passed via stdin (#1342) 2022-12-22 16:40:15 -05:00
Charlie Marsh
451047c30d Exclude directly-passed files nested in excluded subdirectories 2022-12-22 15:08:11 -05:00
Charlie Marsh
6907df489b Extend false-positive list for flake8-boolean-trap (#1338) 2022-12-22 10:56:04 -05:00
Charlie Marsh
970f882b03 Set force-exclude for pre-commit in README (#1337) 2022-12-22 10:51:20 -05:00
Charlie Marsh
3eff9a2860 Allow unittest methods in flake8-boolean-trap (#1333) 2022-12-22 08:40:22 -05:00
Charlie Marsh
a4a24a0ef3 Add some more repositories to the user list (#1328) 2022-12-21 22:16:47 -05:00
Charlie Marsh
48e3c046b0 Fix integration tests 2022-12-21 21:25:37 -05:00
Charlie Marsh
03e4f5be8a Bump version to 0.0.191 2022-12-21 21:16:21 -05:00
Charlie Marsh
99657b7d92 Implement E401 ("multiple imports on one line") (#1326) 2022-12-21 21:15:57 -05:00
Charlie Marsh
40377aa1fc Move number of errors to the bottom of the output summary (#1325) 2022-12-21 21:04:26 -05:00
Charlie Marsh
2a37017e8c Add src to Settings hash 2022-12-21 21:01:20 -05:00
Charlie Marsh
ff66d08cef Run generate-options 2022-12-21 20:58:14 -05:00
Charlie Marsh
dad8035eef Support shell expansion in src field (#1324) 2022-12-21 20:57:20 -05:00
Charlie Marsh
bf5fec342c Support shell expansion in extend paths (#1323) 2022-12-21 20:46:38 -05:00
Charlie Marsh
66a6c81ebf Infer package roots when running via stdin (#1321) 2022-12-21 20:30:10 -05:00
Charlie Marsh
5c70f5044b Improve debug logging in flake8-to-ruff (#1320) 2022-12-21 20:05:48 -05:00
Charlie Marsh
953d141ab2 Support code redirects in flake8-to-ruff (#1318) 2022-12-21 19:31:20 -05:00
Charlie Marsh
07dba46039 Extract line length from pyproject.toml Black section (#1317) 2022-12-21 19:05:18 -05:00
Ran Benita
3b02da9d7b Fix false positive DTZ001 on datetime(2000, 1, 1, 0, 0, 0, 0, utc) (#1308) 2022-12-21 19:03:36 -05:00
Charlie Marsh
20234c6156 Bump version to 0.0.190 2022-12-21 16:01:48 -05:00
Charlie Marsh
de767cc026 Avoid used-prior-global-declaration false-positives in f-strings (#1314) 2022-12-21 14:34:09 -05:00
Charlie Marsh
ce1663d302 Allow overriding cache location via RUFF_CACHE_DIR (#1312) 2022-12-21 14:24:10 -05:00
Charlie Marsh
f40e4bcd14 Avoid flagging RUF100 as a RUF100 violation (#1305) 2022-12-20 17:40:10 -05:00
Charlie Marsh
e7d40d435f Avoid F821 false positives for Mypy extensions (#1304) 2022-12-20 16:29:33 -05:00
Charlie Marsh
ef8fe31c0c Bump version to 0.0.189 2022-12-20 13:26:17 -05:00
Charlie Marsh
226f682c99 Avoid DTZ007 false-positives for non-string arguments (#1300) 2022-12-20 13:20:53 -05:00
Hannes Käufler
468ffd29fb [Stylistic/non-functional] Use an r# format string to make json easier to read (#1299) 2022-12-20 12:55:21 -05:00
Charlie Marsh
a61126ab23 Run generate-options 2022-12-19 23:19:05 -05:00
Charlie Marsh
54c7c25861 Revert test changes to setup.py 2022-12-19 20:09:47 -05:00
Charlie Marsh
eff7700d92 Add --force-exclude setting to force exclusions with pre-commit (#1295) 2022-12-19 20:08:59 -05:00
Charlie Marsh
8934f6938d Avoid RET504 errors for intermediary function calls (#1294) 2022-12-19 19:48:09 -05:00
Charlie Marsh
8f0fc3033a Update Arg section checking to match latest pydocstyle (#1293) 2022-12-19 16:39:42 -05:00
Charlie Marsh
4107bc828d Bump version to 0.0.188 2022-12-19 12:18:06 -05:00
Charlie Marsh
706d28cabc Rename PDV checks to PD (#1288) 2022-12-19 00:20:28 -05:00
Charlie Marsh
4da2264722 Avoid T201 errors for print(..., file=fp)-like calls (#1287) 2022-12-19 00:10:07 -05:00
Charlie Marsh
bf88c815aa Move flake8-debugger tests into flake8-debugger subdirectory (#1286) 2022-12-18 22:06:42 -05:00
Yasu_umi
8a4831dd5b Implement flake8-datetimez (#1270) 2022-12-18 22:06:06 -05:00
Charlie Marsh
b5ab492a70 Bump version to 0.0.187 2022-12-18 20:09:02 -05:00
Charlie Marsh
1fc09ebd5c Fix inverted E501 condition (#1285) 2022-12-18 20:08:30 -05:00
Charlie Marsh
6cf047976c Bump pygrep-hooks tally in README 2022-12-18 18:05:32 -05:00
Reiner Gerecke
87465daacc pygrep-hooks - deprecated use of logging.warn & no blanket type ignore (#1275) 2022-12-18 18:04:21 -05:00
Chris Brendel
a52bed7101 Use --stdin-filename when resolving configuration files (#1281) 2022-12-18 17:51:55 -05:00
Anders Kaseorg
20ac823778 generate-check-code-prefix: Run rustfmt automatically; only write if changed (#1282) 2022-12-18 17:46:23 -05:00
Charlie Marsh
1028ed3565 Bump version to 0.0.186 2022-12-18 14:30:30 -05:00
Anders Kaseorg
98897db6ac Add packaging status badge from repology (#1276) 2022-12-18 14:27:29 -05:00
Honkertonken
5ce4262112 Readme : Fix incorrect exmaple. (#1277) 2022-12-18 12:04:48 -05:00
Charlie Marsh
6b2359384d Print redirect warnings exactly once per code (#1280) 2022-12-18 12:03:49 -05:00
Harutaka Kawamura
d3443d7c19 Update RustPython to use correct Tuple location (#1278) 2022-12-18 08:53:57 -05:00
Anders Kaseorg
04b1e1de6f README: Add missing backtick (#1274) 2022-12-18 00:29:33 -05:00
Anders Kaseorg
c93c85300f Repair corrupted PDV007, PDV009 messages (#1273) 2022-12-18 00:29:12 -05:00
Charlie Marsh
73ed6f8654 Touch-up README 2022-12-17 21:38:45 -05:00
Charlie Marsh
eb183645f3 Add ruff-lsp to README (#1272)
Add ruff-lsp to README
2022-12-17 21:37:11 -05:00
Charlie Marsh
ef17aa93da Add ruff-lsp to README (#1272) 2022-12-17 21:37:00 -05:00
Charlie Marsh
f366b0147f Add ruff-lsp to README (#1272) 2022-12-17 21:35:44 -05:00
Charlie Marsh
fc88fa35ff Add instructions for Sublime Text installation (#1271) 2022-12-17 16:22:50 -05:00
Charlie Marsh
a2806eb8ef Bump version to 0.0.185 2022-12-16 23:47:56 -05:00
Charlie Marsh
89d919eac5 Re-remove W605_1.py from Black compatibility test 2022-12-16 23:17:27 -05:00
Charlie Marsh
5ad77fbc8d Move checkers into their own module (#1268) 2022-12-16 22:55:47 -05:00
Charlie Marsh
9cb18a481b Separate line-based checker from noqa enforcement (#1267) 2022-12-16 22:49:27 -05:00
Charlie Marsh
2393e270ed Change a few more methods to take AsRef<Path> 2022-12-16 21:38:52 -05:00
Charlie Marsh
f36e6035c8 Change a few methods to take AsRef<Path> 2022-12-16 21:28:19 -05:00
Charlie Marsh
ecf0dd05d6 Auto-detect same-package imports (#1266) 2022-12-16 21:19:11 -05:00
Charlie Marsh
5f67ee93f7 Replace cache bool with an enum 2022-12-16 15:45:30 -05:00
Charlie Marsh
1e19142d0e Bump version to 0.0.184 2022-12-16 14:36:25 -05:00
Charlie Marsh
6a95dade6d Actually check-in snapshots for #1265 2022-12-16 14:36:00 -05:00
Charlie Marsh
d6e765877e Enable autofix for __init__ method with missing None-return (#1265) 2022-12-16 14:28:56 -05:00
Charlie Marsh
e4d36bae57 Replace ignore_noqa and autofix booleans with enums (#1264) 2022-12-16 14:01:25 -05:00
Harutaka Kawamura
e3531276a7 Fix F501 (line-too-long) start location (#1262) 2022-12-16 11:29:47 -05:00
Charlie Marsh
634553f188 Add ignore-variadic-names options to flake8-unused-arguments (#1261) 2022-12-16 00:22:38 -05:00
Edgar R. M
4ff0b75045 test: Fix flake8-errmsg snapshots (#1260) 2022-12-15 23:53:15 -05:00
Charlie Marsh
481d668511 Add flake8-errmsg to README 2022-12-15 23:16:38 -05:00
Charlie Marsh
a9f56ee76e Bump version to 0.0.183 2022-12-15 23:15:12 -05:00
Charlie Marsh
b4bfa87104 Avoid removing partially-unused imports (#1259) 2022-12-15 23:13:58 -05:00
Charlie Marsh
b9f42bf5e5 Remove extraneous test file 2022-12-15 23:12:19 -05:00
Edgar R. M
8281d414ca Implement flake8-errmsg (#1258) 2022-12-15 23:10:59 -05:00
Charlie Marsh
7e45a9f2e2 Avoid generating invalid statements when deleting from multi-statement lines (#1253) 2022-12-15 22:17:31 -05:00
Reiner Gerecke
a000cd4a09 Test to prevent continious reformatting when used together with black (#1206) 2022-12-15 15:26:41 -05:00
Martin Lehoux
d8b4b92733 Implement U016: Remove six compatibility code (#1013) 2022-12-15 14:16:58 -05:00
Edgar R. M
27de342e75 Implement pandas-vet (#1235) 2022-12-15 14:01:01 -05:00
Charlie Marsh
d805067683 Avoid fixing E711 and E712 issues that would cause F632 (#1248) 2022-12-15 12:08:31 -05:00
Charlie Marsh
1ea2e93f8e Bump version to 0.0.182 2022-12-14 22:57:22 -05:00
Charlie Marsh
dc180dc277 Negate ignore_names condition 2022-12-14 22:50:26 -05:00
Charlie Marsh
6be910ae07 Use more precise ranges for function and class checks (#1247) 2022-12-14 22:40:00 -05:00
Charlie Marsh
ba85eb846c Run cargo fmt 2022-12-14 21:52:44 -05:00
Charlie Marsh
d067efe265 Treat extend-* configuration options as "always extended" (#1245) 2022-12-14 20:22:40 -05:00
Charlie Marsh
549ea2f85f Ignore any pyproject.toml without a [tool.ruff] section (#1243) 2022-12-14 19:35:52 -05:00
Charlie Marsh
d814ebd21f Bump version to 0.0.181 2022-12-14 17:35:36 -05:00
Charlie Marsh
3f272b6cf8 Enable opt-out of .gitignore checks via respect-gitignore flag (#1242) 2022-12-14 16:54:23 -05:00
Charlie Marsh
76891a8c07 Always check zero-depth CLI paths (#1241) 2022-12-14 16:32:02 -05:00
Charlie Marsh
e389201b5f Add new .gitignore behavior to BREAKING_CHANGES.md (#1240) 2022-12-14 16:04:06 -05:00
Charlie Marsh
4b2020d03a Automatically ignore files specified in .gitignore (#1234) 2022-12-14 15:58:40 -05:00
Charlie Marsh
0aa356c96c Avoid converting expression to statement in invald contexts (#1239) 2022-12-14 13:57:25 -05:00
Charlie Marsh
630b4b627d Apply fix to all errors in E711 and E712 autofix (#1238) 2022-12-14 13:29:56 -05:00
Charlie Marsh
854cd14842 Bump version to 0.0.180 2022-12-14 13:21:10 -05:00
Chris Brendel
6b93c8403f Apply CLI options even when no pyproject.toml is found (#1232) 2022-12-13 22:55:04 -05:00
Charlie Marsh
765d21c7b0 Bump version to 0.0.179 2022-12-13 10:17:16 -05:00
Charlie Marsh
a58b9b5063 Upgrade RustPython to support parenthesized context managers (#1228) 2022-12-13 10:16:43 -05:00
Charlie Marsh
f3e11a30cb Bump version to 0.0.178 2022-12-12 22:06:04 -05:00
Charlie Marsh
2f3b5367ff Add a note on extends to README 2022-12-12 21:36:39 -05:00
Charlie Marsh
92bc417e4e Add support for glob patterns in src (#1225) 2022-12-12 21:35:03 -05:00
Charlie Marsh
9853b0728b Enable configuration files to "extend" other configuration files (#1219) 2022-12-12 20:28:22 -05:00
Charlie Marsh
77709dcc41 Remove underscore from extend_exclude 2022-12-12 16:34:16 -05:00
Charlie Marsh
b0cb5fc7ef Document current behavior around pyproject.toml discovery (#1213) 2022-12-12 11:49:21 -05:00
Charlie Marsh
d6f51e55dd Remove extraneous test_project 2022-12-12 10:53:12 -05:00
Charlie Marsh
4bb6b4851a Rename p to path 2022-12-12 10:51:24 -05:00
Charlie Marsh
54c5ded938 Move settings path discovery into its own function 2022-12-12 10:50:08 -05:00
Charlie Marsh
0157fedab5 Move Python file resolution into resolver.rs (#1211) 2022-12-12 10:43:50 -05:00
Charlie Marsh
cd69610741 Use --config everywhere if provided (#1210) 2022-12-12 10:28:00 -05:00
Charlie Marsh
a3d06d0005 Move more commands into commands.rs (#1209) 2022-12-12 10:22:47 -05:00
Charlie Marsh
ac6fa1dc88 Simplify some logic around configuration detection (#1197) 2022-12-12 10:15:05 -05:00
Charlie Marsh
73794fc299 Resolve hierarchical settings and Python files in a single filesystem pass (#1205) 2022-12-12 10:13:52 -05:00
Charlie Marsh
0adc9ed259 Support hierarchical settings for nested directories (#1190) 2022-12-12 10:12:23 -05:00
Charlie Marsh
19e9eb1af8 Bump version to 0.0.177 2022-12-11 22:38:52 -05:00
Anders Kaseorg
e57044800c Fix quotes in SIM118 error message (#1204) 2022-12-11 22:30:39 -05:00
Charlie Marsh
ae8ff7cb7f Add notes around python-lsp-ruff (#1202) 2022-12-11 17:36:20 -05:00
Charlie Marsh
c05914f222 Avoid inserting extra newlines for comment-delimited import blocks (#1201) 2022-12-11 17:13:09 -05:00
Charlie Marsh
24179655b8 Fix 'a test' reference 2022-12-11 13:31:14 -05:00
Charlie Marsh
d27b419e68 Run cargo dev generate-options 2022-12-11 10:34:52 -05:00
Charlie Marsh
9fc7a32a24 Sort list in README 2022-12-11 10:25:27 -05:00
Charlie Marsh
9161b866b5 Bump version to 0.0.176 2022-12-11 10:19:50 -05:00
Reiner Gerecke
38141a6f14 Check for outdated auto-generated files in CI (#1192) 2022-12-11 10:18:57 -05:00
Charlie Marsh
aa5402fc0e Add flake8-simplify to flake8-to-ruff 2022-12-11 10:10:46 -05:00
Charlie Marsh
99f077aa4e Add missing hash in README comment 2022-12-11 10:05:32 -05:00
Reiner Gerecke
7f25d1ec70 Implement SIM118 (key in dict) of flake8-simplify (#1195) 2022-12-11 10:05:11 -05:00
Charlie Marsh
360b033e04 Avoid F821 false positive on annotated global (#1196) 2022-12-11 10:04:06 -05:00
Reiner Gerecke
247dcc9f9c Mark C413 as fixable (#1191) 2022-12-11 09:07:51 -05:00
Charlie Marsh
c86e52193c Bump version to 0.0.175 2022-12-10 21:23:19 -05:00
Harutaka Kawamura
efdc4e801d Upgrade RustPython to fix end location of implicitly concatenated strings (#1187) 2022-12-10 19:16:01 -05:00
Charlie Marsh
f8f2eeed35 Enable --no-show-source for consistency (#1189) 2022-12-10 19:09:49 -05:00
Charlie Marsh
8fa414b67e Move configuration-CLI resolution into dedicated methods (#1188) 2022-12-10 19:07:38 -05:00
Charlie Marsh
484d7a30bd Add TODO around nested globals 2022-12-10 17:44:08 -05:00
Charlie Marsh
fb681c614a Move string formatting checks to plugins (#1185) 2022-12-10 16:43:21 -05:00
Reiner Gerecke
06ed125771 Add autofix for F504 and F522 (#1184) 2022-12-10 16:33:09 -05:00
Charlie Marsh
74668915b0 Remove serialization format from Settings struct (#1183) 2022-12-10 13:38:59 -05:00
Charlie Marsh
6da3de25ba Add jupyter_server to README (#1182) 2022-12-10 12:10:27 -05:00
Charlie Marsh
63b3e00c97 Bump version to 0.0.174 2022-12-10 12:08:48 -05:00
Charlie Marsh
39440aa274 Create function and lambda scopes eagerly (#1181) 2022-12-10 12:08:33 -05:00
Charlie Marsh
add96d3dc5 Implement E0117 (nonlocal-without-binding) (#1180) 2022-12-10 11:41:57 -05:00
Charlie Marsh
6f8e0224d0 Implement W0602 (global-variable-not-assigned) (#1179) 2022-12-10 11:33:24 -05:00
Charlie Marsh
b8bbafd85b Flag global usages prior to global declarations (#1178) 2022-12-10 11:19:24 -05:00
Charlie Marsh
40b54d3e8c Ignore imports in class scopes (#1176) 2022-12-10 10:23:33 -05:00
Charlie Marsh
2b44941d63 Add pacman instructions to README (#1175) 2022-12-10 10:00:01 -05:00
Charlie Marsh
257bd7f1d7 Bump version to 0.0.173 2022-12-09 23:23:12 -05:00
Charlie Marsh
5728dceef0 Add note around redefinitions 2022-12-09 23:18:51 -05:00
Charlie Marsh
6739602806 Mark redefined-but-unused imports as unused regardless of scope (#1173) 2022-12-09 23:17:33 -05:00
Charlie Marsh
305326f7d7 Remove some string clones from docstring helpers (#1172) 2022-12-09 22:30:34 -05:00
Charlie Marsh
69866f5461 Extract docstring exactly once (#1171) 2022-12-09 22:21:16 -05:00
Charlie Marsh
41ca29c4f4 Add TODO in redefined_by_function 2022-12-09 21:19:57 -05:00
Charlie Marsh
b35a804f9d Bump version to 0.0.172 2022-12-09 17:47:34 -05:00
Charlie Marsh
e594ed6528 Implement D301 (backslash checks) (#1169) 2022-12-09 17:44:18 -05:00
Charlie Marsh
197645d90d Always use raw docstrings for pydocstyle rules (#1167) 2022-12-09 17:31:04 -05:00
Charlie Marsh
26d3ff5a3a Add pyflakes test suite for annotations (#1166) 2022-12-09 16:28:07 -05:00
Charlie Marsh
0dacf61153 Implement F842 (UnusedAnnotation) (#1165) 2022-12-09 12:42:03 -05:00
Charlie Marsh
a6251360b7 Avoid RET false-positives for usages in f-strings (#1163) 2022-12-09 12:28:09 -05:00
Charlie Marsh
2965e2561d Clarify combination of combine-as-imports and force-wrap-aliases (#1162) 2022-12-09 12:20:15 -05:00
Charlie Marsh
a19050b8a4 Update README.md 2022-12-08 23:39:01 -05:00
Charlie Marsh
dfd6225d85 Bump version to 0.0.171 2022-12-08 23:18:48 -05:00
Charlie Marsh
a0a6327fae Only allowlist noqa et al at the start of a comment (#1157) 2022-12-08 23:10:36 -05:00
Charlie Marsh
db815a565f Run release job on release: published event (#1156) 2022-12-08 23:05:28 -05:00
Charlie Marsh
3bacdafd1c Improve some __all__ handling cases (#1155) 2022-12-08 23:03:23 -05:00
Charlie Marsh
6403e3630d Fix flaky unused import test 2022-12-08 22:51:13 -05:00
Charlie Marsh
229eab6f42 Improve some behavior around global handling (#1154) 2022-12-08 22:47:19 -05:00
Charlie Marsh
e33582fb0e Add pyflakes import test suite (#1151) 2022-12-08 22:23:37 -05:00
Charlie Marsh
aaeab0ecf1 Implement F811 (RedefinedWhileUnused) (#1137) 2022-12-08 21:31:08 -05:00
Charlie Marsh
f9a16d9c44 Fix GitHub link 2022-12-08 20:54:54 -05:00
Charlie Marsh
2aa884eb9b Re-implement the entire test_undefined_names.py test suite (#1150) 2022-12-08 20:53:01 -05:00
Charlie Marsh
84fa64d98c Move bindings to an arena (#1147) 2022-12-08 19:48:00 -05:00
Charlie Marsh
c1b1ac069e Include else block in break detection (#1143) 2022-12-08 11:53:31 -05:00
Charlie Marsh
a710e35ebc Bump version to 0.0.170 2022-12-08 11:36:24 -05:00
Charlie Marsh
49df43bb78 Use single newlines in .pyi import sorting (#1142) 2022-12-08 11:34:41 -05:00
Charlie Marsh
e338d9acbe Remove 'consider' language from check messages (#1135) 2022-12-07 20:10:36 -05:00
Charlie Marsh
5c8655f479 Bump ruff_macros to 0.0.169 2022-12-07 19:10:16 -05:00
Charlie Marsh
60987888a2 Re-increase max iterations to 100 2022-12-07 19:10:03 -05:00
Charlie Marsh
a81581c781 Bump ruff_macros to 0.0.168 2022-12-07 19:08:18 -05:00
Charlie Marsh
3152dd7a8e Don't prompt users to --fix if they ran with --fix (#1133) 2022-12-07 19:07:51 -05:00
Charlie Marsh
528416f07a Rename I252 to TID252; add redirects for all renamed codes (#1129) 2022-12-07 15:12:22 -05:00
Charlie Marsh
4405a6a903 Bump version to 0.0.168 2022-12-07 13:18:40 -05:00
Charlie Marsh
35fa2a3c32 Convert more BTree usages to Fx (#1112) 2022-12-07 12:21:12 -05:00
Charlie Marsh
bb67fbb73a Implement unused argument detection (ARG) (#1126)
Detect unused arguments
2022-12-07 12:15:41 -05:00
Charlie Marsh
d698c6123e Bump version to 0.0.167 2022-12-07 10:37:31 -05:00
Charlie Marsh
9579faffa8 Avoid flagging bare exception issues when exception is re-raised (#1124) 2022-12-07 10:37:08 -05:00
Phillip Verheyden
9c6e8c7644 Auto-generate the rules table of contents (#1121) 2022-12-07 10:03:42 -05:00
Charlie Marsh
7abecd4f0e Implement B905 (#1122) 2022-12-07 10:01:24 -05:00
Phillip Verheyden
b8ff209af8 Encode prefixes in README headings not just in TOC (#1109) 2022-12-07 09:24:49 -05:00
Jeong YunWon
c5451cd8ad Reduce indents (#1116) 2022-12-07 09:20:33 -05:00
Jonathan Plasse
92b9ab3010 Add aiter() and anext() to BUILTINS (#1118) 2022-12-07 09:20:06 -05:00
Edgar R. M
f2ac8c4ec2 Add flake8-import-conventions to TOC in readme (#1114) 2022-12-06 21:27:04 -05:00
Charlie Marsh
80e2f0c92e Bump version to 0.0.166 2022-12-06 16:06:19 -05:00
Edgar R. M
ea550abd3c Implement flake8-import-conventions (#1098) 2022-12-06 16:01:17 -05:00
Charlie Marsh
5c26777e4c Avoid flagging ANN errors in @overload implementations (#1110) 2022-12-06 12:46:38 -05:00
Laurent Baillet
6eb6b6eede Update readme in order to match pylint prefixes (#1105) 2022-12-06 08:59:45 -05:00
1530 changed files with 95596 additions and 31388 deletions

10
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,10 @@
<!--
Thank you for taking the time to report an issue! We're glad to have you involved with Ruff.
If you're filing a bug report, please consider including the following information:
- A minimal code snippet that reproduces the bug.
- The command you invoked (e.g., `ruff /path/to/file.py --fix`), ideally including the `--isolated` flag.
- The current Ruff settings (any relevant sections from your `pyproject.toml`).
- The current Ruff version (`ruff --version`).
-->

View File

@@ -6,13 +6,17 @@ on:
pull_request:
branches: [main]
concurrency:
group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: true
env:
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
RUSTUP_MAX_RETRIES: 10
jobs:
cargo_build:
cargo-build:
name: "cargo build"
runs-on: ubuntu-latest
steps:
@@ -20,21 +24,16 @@ jobs:
- uses: actions-rs/toolchain@v1
with:
profile: minimal
- uses: actions/cache@v3
env:
cache-name: cache-cargo
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- run: cargo build --all --release
toolchain: nightly-2022-11-01
override: true
- uses: Swatinem/rust-cache@v1
- run: cargo build --all
- run: ./target/debug/ruff_dev generate-all
- run: git diff --quiet README.md || echo "::error file=README.md::This file is outdated. Run 'cargo +nightly dev generate-all'."
- run: git diff --quiet ruff.schema.json || echo "::error file=ruff.schema.json::This file is outdated. Run 'cargo +nightly dev generate-all'."
- run: git diff --exit-code -- README.md ruff.schema.json
cargo_fmt:
cargo-fmt:
name: "cargo fmt"
runs-on: ubuntu-latest
steps:
@@ -45,18 +44,6 @@ jobs:
toolchain: nightly-2022-11-01
override: true
components: rustfmt
- uses: actions/cache@v3
env:
cache-name: cache-cargo
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- run: cargo fmt --all --check
cargo_clippy:
@@ -70,21 +57,12 @@ jobs:
toolchain: nightly-2022-11-01
override: true
components: clippy
- uses: actions/cache@v3
env:
cache-name: cache-cargo
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
target: wasm32-unknown-unknown
- uses: Swatinem/rust-cache@v1
- run: cargo clippy --workspace --all-targets --all-features -- -D warnings -W clippy::pedantic
- run: cargo clippy -p ruff --target wasm32-unknown-unknown --all-features -- -D warnings -W clippy::pedantic
cargo_test:
cargo-test:
name: "cargo test"
runs-on: ubuntu-latest
steps:
@@ -94,21 +72,49 @@ jobs:
profile: minimal
toolchain: nightly-2022-11-01
override: true
- uses: actions/cache@v3
env:
cache-name: cache-cargo
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- run: cargo test --all
- uses: Swatinem/rust-cache@v1
- run: cargo install cargo-insta
- run: pip install black[d]==22.12.0
- name: Run tests
run: |
cargo insta test --all --delete-unreferenced-snapshots
git diff --exit-code
- run: cargo test --package ruff_cli --test black_compatibility_test -- --ignored
# Check for broken links in the documentation.
# Setting RUSTDOCFLAGS because `cargo doc --check` isn't yet implemented (https://github.com/rust-lang/cargo/issues/10025).
- run: RUSTDOCFLAGS="-D warnings" cargo doc --all --no-deps
maturin_build:
# TODO(charlie): Re-enable the `wasm-pack` tests.
# See: https://github.com/charliermarsh/ruff/issues/1425
# wasm-pack-test:
# name: "wasm-pack test"
# runs-on: ubuntu-latest
# env:
# WASM_BINDGEN_TEST_TIMEOUT: 60
# steps:
# - uses: actions/checkout@v3
# - uses: actions-rs/toolchain@v1
# with:
# profile: minimal
# toolchain: nightly-2022-11-01
# override: true
# - uses: actions/cache@v3
# env:
# cache-name: cache-cargo
# with:
# path: |
# ~/.cargo/registry
# ~/.cargo/git
# key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
# restore-keys: |
# ${{ runner.os }}-build-${{ env.cache-name }}-
# ${{ runner.os }}-build-
# ${{ runner.os }}-
# - uses: jetli/wasm-pack-action@v0.4.0
# - uses: jetli/wasm-bindgen-action@v0.2.0
# - run: wasm-pack test --node
maturin-build:
name: "maturin build"
runs-on: ubuntu-latest
steps:
@@ -118,20 +124,21 @@ jobs:
profile: minimal
toolchain: nightly-2022-11-01
override: true
- uses: Swatinem/rust-cache@v1
- uses: actions/setup-python@v4
with:
python-version: "3.10"
python-version: "3.11"
- run: pip install maturin
- uses: actions/cache@v3
env:
cache-name: cache-cargo
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- run: maturin build -b bin
typos:
name: Spell Check with Typos
runs-on: ubuntu-latest
steps:
- name: Checkout Actions Repository
uses: actions/checkout@v2
- name: Check spelling of file.txt
uses: crate-ci/typos@master
with:
files: .

50
.github/workflows/playground.yaml vendored Normal file
View File

@@ -0,0 +1,50 @@
name: "[Playground] Release"
on:
workflow_dispatch:
push:
branches: [main]
env:
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
RUSTUP_MAX_RETRIES: 10
jobs:
publish:
runs-on: ubuntu-latest
env:
CF_API_TOKEN_EXISTS: ${{ secrets.CF_API_TOKEN != '' }}
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly-2022-11-01
override: true
target: wasm32-unknown-unknown
- uses: actions/setup-node@v3
with:
node-version: 18
cache: "npm"
cache-dependency-path: playground/package-lock.json
- uses: jetli/wasm-pack-action@v0.4.0
- uses: jetli/wasm-bindgen-action@v0.2.0
- name: "Run wasm-pack"
run: wasm-pack build --target web --out-dir playground/src/pkg . -- -p ruff
- name: "Install Node dependencies"
run: npm ci
working-directory: playground
- name: "Run TypeScript checks"
run: npm run check
working-directory: playground
- name: "Build JavaScript bundle"
run: npm run build
working-directory: playground
- name: "Deploy to Cloudflare Pages"
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
uses: cloudflare/wrangler-action@2.0.0
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CF_ACCOUNT_ID }}
command: pages publish playground/dist --project-name=ruff --branch ${GITHUB_HEAD_REF} --commit-hash ${GITHUB_SHA}

View File

@@ -1,9 +1,8 @@
name: "[ruff] Release"
on:
create:
tags:
- v*
release:
types: [published]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
@@ -294,3 +293,6 @@ jobs:
run: |
pip install --upgrade twine
twine upload --skip-existing *
- name: Update pre-commit mirror
run: |
curl -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer ${{ secrets.RUFF_PRE_COMMIT_PAT }}" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/repos/charliermarsh/ruff-pre-commit/dispatches --data '{"event_type": "pypi_release"}'

1
.gitignore vendored
View File

@@ -181,3 +181,4 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
.idea/
.vimspector.json

View File

@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.0.165
rev: v0.0.227
hooks:
- id: ruff
@@ -8,3 +8,11 @@ repos:
rev: v0.10.1
hooks:
- id: validate-pyproject
- repo: local
hooks:
- id: cargo-fmt
name: cargo fmt
entry: cargo fmt --
language: rust
types: [rust]

54
BREAKING_CHANGES.md Normal file
View File

@@ -0,0 +1,54 @@
# Breaking Changes
## 0.0.226
### `misplaced-comparison-constant` (`PLC2201`) was deprecated in favor of `SIM300` ([#1980](https://github.com/charliermarsh/ruff/pull/1980))
These two rules contain (nearly) identical logic. To deduplicate the rule set, we've upgraded
`SIM300` to handle a few more cases, and deprecated `PLC2201` in favor of `SIM300`.
## 0.0.225
### `@functools.cache` rewrites have been moved to a standalone rule (`UP033`) ([#1938](https://github.com/charliermarsh/ruff/pull/1938))
Previously, `UP011` handled both `@functools.lru_cache()`-to-`@functools.lru_cache` conversions,
_and_ `@functools.lru_cache(maxsize=None)`-to-`@functools.cache` conversions. The latter has been
moved out to its own rule (`UP033`). As such, some `# noqa: UP011` comments may need to be updated
to reflect the change in rule code.
## 0.0.222
### `--max-complexity` has been removed from the CLI ([#1877](https://github.com/charliermarsh/ruff/pull/1877))
The McCabe plugin's `--max-complexity` setting has been removed from the CLI, for consistency with
the treatment of other, similar settings.
To set the maximum complexity, use the `max-complexity` property in your `pyproject.toml` file,
like so:
```toml
[tool.ruff.mccabe]
max-complexity = 10
```
## 0.0.181
### Files excluded by `.gitignore` are now ignored ([#1234](https://github.com/charliermarsh/ruff/pull/1234))
Ruff will now avoid checking files that are excluded by `.ignore`, `.gitignore`,
`.git/info/exclude`, and global `gitignore` files. This behavior is powered by the [`ignore`](https://docs.rs/ignore/latest/ignore/struct.WalkBuilder.html#ignore-rules)
crate, and is applied in addition to Ruff's built-in `exclude` system.
To disable this behavior, set `respect-gitignore = false` in your `pyproject.toml` file.
Note that hidden files (i.e., files and directories prefixed with a `.`) are _not_ ignored by
default.
## 0.0.178
### Configuration files are now resolved hierarchically ([#1190](https://github.com/charliermarsh/ruff/pull/1190))
`pyproject.toml` files are now resolved hierarchically, such that for each Python file, we find
the first `pyproject.toml` file in its path, and use that to determine its lint settings.
See the [README](https://github.com/charliermarsh/ruff#pyprojecttoml-discovery) for more.

View File

@@ -9,6 +9,15 @@ free to submit a PR. For larger changes (e.g., new lint rules, new functionality
options), consider submitting an [Issue](https://github.com/charliermarsh/ruff/issues) outlining
your proposed change.
If you're looking for a place to start, we recommend implementing a new lint rule (see:
[_Adding a new lint rule_](#example-adding-a-new-lint-rule), which will allow you to learn from and
pattern-match against the examples in the existing codebase. Many lint rules are inspired by
existing Python plugins, which can be used as a reference implementation.
As a concrete example: consider taking on one of the rules in [`flake8-simplify`](https://github.com/charliermarsh/ruff/issues/998),
and looking to the originating [Python source](https://github.com/MartinThoma/flake8-simplify) for
guidance.
### Prerequisites
Ruff is written in Rust. You'll need to install the
@@ -45,66 +54,71 @@ prior to merging.
### Example: Adding a new lint rule
There are four phases to adding a new lint rule:
At a high level, the steps involved in adding a new lint rule are as follows:
1. Define the rule in `src/checks.rs`.
2. Define the _logic_ for triggering the rule in `src/check_ast.rs` (for AST-based checks),
`src/check_tokens.rs` (for token-based checks), or `src/check_lines.rs` (for text-based checks).
3. Add a test fixture.
4. Update the generated files (documentation and generated code).
1. Create a file for your rule (e.g., `src/rules/flake8_bugbear/rules/abstract_base_class.rs`).
2. In that file, define a violation struct. You can grep for `define_violation!` to see examples.
3. Map the violation struct to a rule code in `src/registry.rs` (e.g., `E402`).
4. Define the logic for triggering the violation in `src/checkers/ast.rs` (for AST-based checks),
`src/checkers/tokens.rs` (for token-based checks), `src/checkers/lines.rs` (for text-based
checks), or `src/checkers/filesystem.rs` (for filesystem-based checks).
5. Add a test fixture.
6. Update the generated files (documentation and generated code).
To define the rule, open up `src/checks.rs`. You'll need to define both a `CheckCode` and
`CheckKind`. As an example, you can grep for `E402` and `ModuleImportNotAtTopOfFile`, and follow the
pattern implemented therein.
To define the violation, start by creating a dedicated file for your rule under the appropriate
rule origin (e.g., `src/rules/flake8_bugbear/rules/abstract_base_class.rs`). That file should
contain a struct defined via `define_violation!`, along with a function that creates the violation
based on any required inputs. (Many of the existing examples live in `src/violations.rs`, but we're
looking to place new rules in their own files.)
To trigger the rule, you'll likely want to augment the logic in `src/check_ast.rs`, which defines
the Python AST visitor, responsible for iterating over the abstract syntax tree and collecting
lint-rule violations as it goes. If you need to inspect the AST, you can run `cargo dev print-ast`
with a Python file. Grep for the `Check::new` invocations to understand how other, similar rules
are implemented.
To trigger the violation, you'll likely want to augment the logic in `src/checkers/ast.rs`, which
defines the Python AST visitor, responsible for iterating over the abstract syntax tree and
collecting diagnostics as it goes.
To add a test fixture, create a file under `resources/test/fixtures`, named to match the `CheckCode`
you defined earlier (e.g., `E402.py`). This file should contain a variety of violations and
non-violations designed to evaluate and demonstrate the behavior of your lint rule. Run Ruff locally
with (e.g.) `cargo run resources/test/fixtures/E402.py --no-cache`. Once you're satisfied with the
output, codify the behavior as a snapshot test by adding a new `testcase` macro to the `mod tests`
section of `src/linter.rs`, like so:
If you need to inspect the AST, you can run `cargo +nightly dev print-ast` with a Python file. Grep
for the `Check::new` invocations to understand how other, similar rules are implemented.
```rust
#[test_case(CheckCode::A001, Path::new("A001.py"); "A001")]
...
```
To add a test fixture, create a file under `resources/test/fixtures/[origin]`, named to match
the code you defined earlier (e.g., `resources/test/fixtures/pycodestyle/E402.py`). This file should
contain a variety of violations and non-violations designed to evaluate and demonstrate the behavior
of your lint rule.
Then, run `cargo test`. Your test will fail, but you'll be prompted to follow-up with
`cargo insta review`. Accept the generated snapshot, then commit the snapshot file alongside the
rest of your changes.
Run `cargo +nightly dev generate-all` to generate the code for your new fixture. Then run Ruff
locally with (e.g.) `cargo run resources/test/fixtures/pycodestyle/E402.py --no-cache --select E402`.
Finally, to update the documentation, run `cargo dev generate-rules-table` from the repo root. To
update the generated prefix map, run `cargo dev generate-check-code-prefix`. Both of these commands
should be run whenever a new check is added to the codebase.
Once you're satisfied with the output, codify the behavior as a snapshot test by adding a new
`test_case` macro in the relevant `src/[origin]/mod.rs` file. Then, run `cargo test --all`.
Your test will fail, but you'll be prompted to follow-up with `cargo insta review`. Accept the
generated snapshot, then commit the snapshot file alongside the rest of your changes.
Finally, regenerate the documentation and generated code with `cargo +nightly dev generate-all`.
### Example: Adding a new configuration option
Ruff's user-facing settings live in two places: first, the command-line options defined with
[clap](https://docs.rs/clap/latest/clap/) via the `Cli` struct in `src/main.rs`; and second, the
`Config` struct defined `src/pyproject.rs`, which is responsible for extracting user-defined
settings from a `pyproject.toml` file.
Ruff's user-facing settings live in a few different places.
Ultimately, these two sources of configuration are merged into the `Settings` struct defined
in `src/settings.rs`, which is then threaded through the codebase.
First, the command-line options are defined via the `Cli` struct in `src/cli.rs`.
To add a new configuration option, you'll likely want to _both_ add a CLI option to `src/main.rs`
_and_ a `pyproject.toml` parameter to `src/pyproject.rs`. If you want to pattern-match against an
existing example, grep for `dummy_variable_rgx`, which defines a regular expression to match against
acceptable unused variables (e.g., `_`).
Second, the `pyproject.toml` options are defined in `src/settings/options.rs` (via the `Options`
struct), `src/settings/configuration.rs` (via the `Configuration` struct), and `src/settings/mod.rs`
(via the `Settings` struct). These represent, respectively: the schema used to parse the
`pyproject.toml` file; an internal, intermediate representation; and the final, internal
representation used to power Ruff.
If the new plugin's configuration should be cached between runs, you'll need to add it to the
`Hash` implementation for `Settings` in `src/settings/mod.rs`.
To add a new configuration option, you'll likely want to modify these latter few files (along with
`cli.rs`, if appropriate). If you want to pattern-match against an existing example, grep for
`dummy_variable_rgx`, which defines a regular expression to match against acceptable unused
variables (e.g., `_`).
Note that plugin-specific configuration options are defined in their own modules (e.g.,
`src/flake8_unused_arguments/settings.rs`).
You may also want to add the new configuration option to the `flake8-to-ruff` tool, which is
responsible for converting `flake8` configuration files to Ruff's TOML format. This logic
lives in `flake8_to_ruff/src/converter.rs`.
Finally, regenerate the documentation and generated code with `cargo +nightly dev generate-all`.
## Release process
As of now, Ruff has an ad hoc release process: releases are cut with high frequency via GitHub

527
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,77 +2,84 @@
members = [
"flake8_to_ruff",
"ruff_dev",
"ruff_cli",
]
default-members = [".", "ruff_cli"]
[package]
name = "ruff"
version = "0.0.165"
version = "0.0.227"
authors = ["Charlie Marsh <charlie.r.marsh@gmail.com>"]
edition = "2021"
rust-version = "1.65.0"
documentation = "https://github.com/charliermarsh/ruff"
homepage = "https://github.com/charliermarsh/ruff"
repository = "https://github.com/charliermarsh/ruff"
readme = "README.md"
license = "MIT"
[lib]
name = "ruff"
crate-type = ["cdylib", "rlib"]
doctest = false
[dependencies]
annotate-snippets = { version = "0.9.1", features = ["color"] }
anyhow = { version = "1.0.66" }
atty = { version = "0.2.14" }
bincode = { version = "1.3.3" }
bitflags = { version = "1.3.2" }
cachedir = { version = "0.3.0" }
cfg-if = { version = "1.0.0" }
chrono = { version = "0.4.21", default-features = false, features = ["clock"] }
clap = { version = "4.0.1", features = ["derive"] }
clap_complete_command = "0.4.0"
clap = { version = "4.0.1", features = ["derive", "env"] }
colored = { version = "2.0.0" }
common-path = { version = "1.0.0" }
dirs = { version = "4.0.0" }
fern = { version = "0.6.1" }
filetime = { version = "0.2.17" }
glob = { version = "0.3.0" }
globset = { version = "0.4.9" }
ignore = { version = "0.4.18" }
itertools = { version = "0.10.5" }
libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "f2f0b7a487a8725d161fe8b3ed73a6758b21e177" }
log = { version = "0.4.17" }
natord = { version = "1.0.9" }
nohash-hasher = { version = "0.2.0" }
notify = { version = "5.0.0" }
num-bigint = { version = "0.4.3" }
num-traits = "0.2.15"
once_cell = { version = "1.16.0" }
path-absolutize = { version = "3.0.14", features = ["once_cell_cache", "use_unix_paths_on_wasm"] }
quick-junit = { version = "0.3.2" }
rayon = { version = "1.5.3" }
regex = { version = "1.6.0" }
ropey = { version = "1.5.0", features = ["cr_lines", "simd"], default-features = false }
ruff_macros = { version = "0.0.161", path = "ruff_macros" }
ruff_macros = { version = "0.0.227", path = "ruff_macros" }
rustc-hash = { version = "1.1.0" }
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "28f9f65ccc625f00835d84bbb5fba274dce5aa89" }
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "28f9f65ccc625f00835d84bbb5fba274dce5aa89" }
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "28f9f65ccc625f00835d84bbb5fba274dce5aa89" }
rustpython-ast = { features = ["unparse"], git = "https://github.com/RustPython/RustPython.git", rev = "ff90fe52eea578c8ebdd9d95e078cc041a5959fa" }
rustpython-common = { git = "https://github.com/RustPython/RustPython.git", rev = "ff90fe52eea578c8ebdd9d95e078cc041a5959fa" }
rustpython-parser = { features = ["lalrpop"], git = "https://github.com/RustPython/RustPython.git", rev = "ff90fe52eea578c8ebdd9d95e078cc041a5959fa" }
schemars = { version = "0.8.11" }
semver = { version = "1.0.16" }
serde = { version = "1.0.147", features = ["derive"] }
serde_json = { version = "1.0.87" }
shellexpand = { version = "3.0.0" }
smallvec = { version = "1.10.0" }
strum = { version = "0.24.1", features = ["strum_macros"] }
strum_macros = { version = "0.24.3" }
textwrap = { version = "0.16.0" }
titlecase = { version = "2.2.1" }
toml = { version = "0.5.9" }
update-informer = { version = "0.5.0", default-features = false, features = ["pypi"], optional = true }
walkdir = { version = "2.3.2" }
[target.'cfg(not(target_family = "wasm"))'.dependencies]
clearscreen = { version = "1.0.10" } # uses which
toml_edit = { version = "0.17.1", features = ["easy"] }
thiserror = { version = "1.0" }
# https://docs.rs/getrandom/0.2.7/getrandom/#webassembly-support
# For (future) wasm-pack support
[target.'cfg(all(target_family = "wasm", target_os = "unknown"))'.dependencies]
getrandom = { version = "0.2.7", features = ["js"] }
console_error_panic_hook = { version = "0.1.7" }
console_log = { version = "0.2.0" }
serde-wasm-bindgen = { version = "0.4" }
js-sys = { version = "0.3.60" }
wasm-bindgen = { version = "0.2.83" }
[dev-dependencies]
assert_cmd = { version = "2.0.4" }
criterion = { version = "0.4.0" }
insta = { version = "1.19.1", features = ["yaml"] }
test-case = { version = "2.2.2" }
wasm-bindgen-test = { version = "0.3.33" }
[features]
default = ["update-informer"]
update-informer = ["dep:update-informer"]
[target.'cfg(not(target_family = "wasm"))'.dev-dependencies]
criterion = { version = "0.4.0" }
[profile.release]
panic = "abort"
@@ -86,6 +93,11 @@ opt-level = 3
[profile.dev.package.similar]
opt-level = 3
# Reduce complexity of a parser function that would trigger a locals limit in a wasm tool.
# https://github.com/bytecodealliance/wasm-tools/blob/b5c3d98e40590512a3b12470ef358d5c7b983b15/crates/wasmparser/src/limits.rs#L29
[profile.dev.package.rustpython-parser]
opt-level = 1
[[bench]]
name = "source_code_locator"
harness = false

547
LICENSE
View File

@@ -19,550 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
The externally maintained libraries from which parts of the Software is derived
are:
- Pyflakes, licensed as follows:
"""
Copyright 2005-2011 Divmod, Inc.
Copyright 2013-2014 Florent Xicluna
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
- autoflake, licensed as follows:
"""
Copyright (C) 2012-2018 Steven Myint
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
- Flake8, licensed as follows:
"""
== Flake8 License (MIT) ==
Copyright (C) 2011-2013 Tarek Ziade <tarek@ziade.org>
Copyright (C) 2012-2016 Ian Cordasco <graffatcolmingov@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
- flake8-2020, licensed as follows:
"""
Copyright (c) 2019 Anthony Sottile
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
- flake8-annotations, licensed as follows:
"""
MIT License
Copyright (c) 2019 - Present S. Co1
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
- flake8-bandit, licensed as follows:
"""
Copyright (c) 2017 Tyler Wince
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
- flake8-blind-except, licensed as follows:
"""
The MIT License (MIT)
Copyright (c) 2014 Elijah Andrews
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
- flake8-bugbear, licensed as follows:
"""
The MIT License (MIT)
Copyright (c) 2016 Łukasz Langa
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
- flake8-comprehensions, licensed as follows:
"""
MIT License
Copyright (c) 2017 Adam Johnson
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
- flake8-debugger, licensed as follows:
"""
MIT License
Copyright (c) 2016 Joseph Kahn
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
- flake8-eradicate, licensed as follows:
"""
MIT License
Copyright (c) 2018 Nikita Sobolev
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
- flake8-tidy-imports, licensed as follows:
"""
MIT License
Copyright (c) 2017 Adam Johnson
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
- flake8-print, licensed as follows:
"""
MIT License
Copyright (c) 2016 Joseph Kahn
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
- flake8-quotes, licensed as follows:
"""
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
- flake8-return, licensed as follows:
"""
MIT License
Copyright (c) 2019 Afonasev Evgeniy
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
- isort, licensed as follows:
"""
The MIT License (MIT)
Copyright (c) 2013 Timothy Edmund Crosley
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
- pep8-naming, licensed as follows:
"""
Copyright © 2013 Florent Xicluna <florent.xicluna@gmail.com>
Licensed under the terms of the Expat License
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
- pycodestyle, licensed as follows:
"""
Copyright © 2006-2009 Johann C. Rocholl <johann@rocholl.net>
Copyright © 2009-2014 Florent Xicluna <florent.xicluna@gmail.com>
Copyright © 2014-2020 Ian Lee <IanLee1521@gmail.com>
Licensed under the terms of the Expat License
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
- pydocstyle, licensed as follows:
"""
Copyright (c) 2012 GreenSteam, <http://greensteam.dk/>
Copyright (c) 2014-2020 Amir Rachum, <http://amir.rachum.com/>
Copyright (c) 2020 Sambhav Kothari, <https://github.com/samj1912>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""
- pygrep-hooks, licensed as follows:
"""
Copyright (c) 2018 Anthony Sottile
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
- pyupgrade, licensed as follows:
"""
Copyright (c) 2017 Anthony Sottile
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
"""
- RustPython, licensed as follows:
"""
MIT License
Copyright (c) 2020 RustPython Team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""

2686
README.md

File diff suppressed because it is too large Load Diff

8
assets/badge/v0.json Normal file
View File

@@ -0,0 +1,8 @@
{
"label": "",
"message": "Ruff",
"logoSvg": "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"128\" height=\"128\"><path d=\"M115.36 61.84 70.22 50.49 114.45 2.4a1.222 1.222 0 0 0-1.54-1.87L12.3 61.98c-.41.25-.64.72-.57 1.2.06.48.4.87.87 1.01l45.07 13.25-44.29 48.16c-.42.46-.44 1.15-.04 1.61.24.29.58.44.94.44.22 0 .45-.06.65-.19l100.78-63.41c.42-.26.64-.75.56-1.22-.08-.49-.43-.88-.91-.99z\" style=\"fill:#fcc21b\"/></svg>",
"logoWidth": 10,
"labelColor": "grey",
"color": "#E15759"
}

8
assets/badge/v1.json Normal file
View File

@@ -0,0 +1,8 @@
{
"label": "",
"message": "Ruff",
"logoSvg": "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"109\" height=\"132\" fill=\"none\"><g filter=\"url(#a)\"><path fill=\"#FCC21B\" d=\"m103.642 61.492-45.14-11.35 44.23-48.09a1.222 1.222 0 0 0-1.54-1.87L.582 61.632c-.41.25-.64.72-.57 1.2.06.48.4.87.87 1.01l45.07 13.25-44.29 48.16c-.42.46-.44 1.15-.04 1.61.24.29.58.44.94.44.22 0 .45-.06.65-.19l100.78-63.41c.42-.26.64-.75.56-1.22-.08-.49-.43-.88-.91-.99Z\"/></g><defs><filter id=\"a\" width=\"108.569\" height=\"131.302\" x=\"0\" y=\"0\" color-interpolation-filters=\"sRGB\" filterUnits=\"userSpaceOnUse\"><feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\"/><feColorMatrix in=\"SourceAlpha\" result=\"hardAlpha\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"/><feOffset dx=\"4\" dy=\"4\"/><feComposite in2=\"hardAlpha\" operator=\"out\"/><feColorMatrix values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0\"/><feBlend in2=\"BackgroundImageFix\" result=\"effect1_dropShadow_7_4\"/><feBlend in=\"SourceGraphic\" in2=\"effect1_dropShadow_7_4\" result=\"shape\"/></filter></defs></svg>",
"logoWidth": 10,
"labelColor": "grey",
"color": "#E15759"
}

84
build.rs Normal file
View File

@@ -0,0 +1,84 @@
use std::fs;
use std::io::{BufRead, BufReader, BufWriter, Write};
use std::path::{Path, PathBuf};
fn main() {
let out_dir = PathBuf::from(std::env::var_os("OUT_DIR").unwrap());
generate_origin_name_and_url(&out_dir);
}
const RULES_SUBMODULE_DOC_PREFIX: &str = "//! Rules from ";
/// The `src/rules/*/mod.rs` files are expected to have a first line such as the
/// following:
///
/// //! Rules from [Pyflakes](https://pypi.org/project/pyflakes/2.5.0/).
///
/// This function extracts the link label and url from these comments and
/// generates the `name` and `url` functions for the `RuleOrigin` enum
/// accordingly, so that they can be used by `ruff_dev::generate_rules_table`.
fn generate_origin_name_and_url(out_dir: &Path) {
println!("cargo:rerun-if-changed=src/rules/");
let mut name_match_arms: String = r#"RuleOrigin::Ruff => "Ruff-specific rules","#.into();
let mut url_match_arms: String = r#"RuleOrigin::Ruff => None,"#.into();
for file in fs::read_dir("src/rules/")
.unwrap()
.flatten()
.filter(|f| f.file_type().unwrap().is_dir() && f.file_name() != "ruff")
{
let mod_rs_path = file.path().join("mod.rs");
let mod_rs_path = mod_rs_path.to_str().unwrap();
let first_line = BufReader::new(fs::File::open(mod_rs_path).unwrap())
.lines()
.next()
.unwrap()
.unwrap();
let Some(comment) = first_line.strip_prefix(RULES_SUBMODULE_DOC_PREFIX) else {
panic!("expected first line in {mod_rs_path} to start with `{RULES_SUBMODULE_DOC_PREFIX}`")
};
let md_link = comment.trim_end_matches('.');
let (name, url) = md_link
.strip_prefix('[')
.unwrap()
.strip_suffix(')')
.unwrap()
.split_once("](")
.unwrap();
let dirname = file.file_name();
let dirname = dirname.to_str().unwrap();
let variant_name = dirname
.split('_')
.map(|part| match part {
"errmsg" => "ErrMsg".to_string(),
"mccabe" => "McCabe".to_string(),
"pep8" => "PEP8".to_string(),
_ => format!("{}{}", part[..1].to_uppercase(), &part[1..]),
})
.collect::<String>();
name_match_arms.push_str(&format!(r#"RuleOrigin::{variant_name} => "{name}","#));
url_match_arms.push_str(&format!(r#"RuleOrigin::{variant_name} => Some("{url}"),"#));
}
write!(
BufWriter::new(fs::File::create(out_dir.join("origin.rs")).unwrap()),
"
impl RuleOrigin {{
pub fn name(&self) -> &'static str {{
match self {{ {name_match_arms} }}
}}
pub fn url(&self) -> Option<&'static str> {{
match self {{ {url_match_arms} }}
}}
}}
"
)
.unwrap();
}

View File

@@ -771,7 +771,7 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "flake8_to_ruff"
version = "0.0.165"
version = "0.0.227"
dependencies = [
"anyhow",
"clap",
@@ -1975,7 +1975,7 @@ dependencies = [
[[package]]
name = "ruff"
version = "0.0.165"
version = "0.0.227"
dependencies = [
"anyhow",
"bincode",
@@ -2028,7 +2028,7 @@ dependencies = [
[[package]]
name = "rustpython-ast"
version = "0.1.0"
source = "git+https://github.com/RustPython/RustPython.git?rev=28f9f65ccc625f00835d84bbb5fba274dce5aa89#28f9f65ccc625f00835d84bbb5fba274dce5aa89"
source = "git+https://github.com/RustPython/RustPython.git?rev=1b6cb170e925a43d605b3fed9f6b878e63e47744#1b6cb170e925a43d605b3fed9f6b878e63e47744"
dependencies = [
"num-bigint",
"rustpython-common",
@@ -2038,7 +2038,7 @@ dependencies = [
[[package]]
name = "rustpython-common"
version = "0.0.0"
source = "git+https://github.com/RustPython/RustPython.git?rev=28f9f65ccc625f00835d84bbb5fba274dce5aa89#28f9f65ccc625f00835d84bbb5fba274dce5aa89"
source = "git+https://github.com/RustPython/RustPython.git?rev=1b6cb170e925a43d605b3fed9f6b878e63e47744#1b6cb170e925a43d605b3fed9f6b878e63e47744"
dependencies = [
"ascii",
"cfg-if 1.0.0",
@@ -2061,7 +2061,7 @@ dependencies = [
[[package]]
name = "rustpython-compiler-core"
version = "0.1.2"
source = "git+https://github.com/RustPython/RustPython.git?rev=28f9f65ccc625f00835d84bbb5fba274dce5aa89#28f9f65ccc625f00835d84bbb5fba274dce5aa89"
source = "git+https://github.com/RustPython/RustPython.git?rev=1b6cb170e925a43d605b3fed9f6b878e63e47744#1b6cb170e925a43d605b3fed9f6b878e63e47744"
dependencies = [
"bincode",
"bitflags",
@@ -2078,7 +2078,7 @@ dependencies = [
[[package]]
name = "rustpython-parser"
version = "0.1.2"
source = "git+https://github.com/RustPython/RustPython.git?rev=28f9f65ccc625f00835d84bbb5fba274dce5aa89#28f9f65ccc625f00835d84bbb5fba274dce5aa89"
source = "git+https://github.com/RustPython/RustPython.git?rev=1b6cb170e925a43d605b3fed9f6b878e63e47744#1b6cb170e925a43d605b3fed9f6b878e63e47744"
dependencies = [
"ahash",
"anyhow",

View File

@@ -1,14 +1,12 @@
[package]
name = "flake8-to-ruff"
version = "0.0.165-dev.0"
version = "0.0.227"
edition = "2021"
[lib]
name = "flake8_to_ruff"
[dependencies]
anyhow = { version = "1.0.66" }
clap = { version = "4.0.1", features = ["derive"] }
colored = { version = "2.0.0" }
configparser = { version = "3.0.2" }
once_cell = { version = "1.16.0" }
regex = { version = "1.6.0" }
@@ -16,7 +14,9 @@ ruff = { path = "..", default-features = false }
rustc-hash = { version = "1.1.0" }
serde = { version = "1.0.147", features = ["derive"] }
serde_json = { version = "1.0.87" }
toml = { version = "0.5.9" }
strum = { version = "0.24.1", features = ["strum_macros"] }
strum_macros = { version = "0.24.3" }
toml_edit = { version = "0.17.1", features = ["easy"] }
[dev-dependencies]

View File

@@ -84,7 +84,7 @@ flake8-to-ruff path/to/.flake8 --plugin flake8-builtins --plugin flake8-quotes
1. Ruff only supports a subset of the Flake configuration options. `flake8-to-ruff` will warn on and
ignore unsupported options in the `.flake8` file (or equivalent). (Similarly, Ruff has a few
configuration options that don't exist in Flake8.)
2. Ruff will omit any error codes that are unimplemented or unsupported by Ruff, including error
2. Ruff will omit any rule codes that are unimplemented or unsupported by Ruff, including rule
codes from unsupported plugins. (See the [Ruff README](https://github.com/charliermarsh/ruff#user-content-how-does-ruff-compare-to-flake8)
for the complete list of supported plugins.)

View File

@@ -0,0 +1,65 @@
[build-system]
requires = [
# The minimum setuptools version is specific to the PEP 517 backend,
# and may be stricter than the version required in `setup.cfg`
"setuptools>=40.6.0,!=60.9.0",
"wheel",
# Must be kept in sync with the `install_requirements` in `setup.cfg`
"cffi>=1.12; platform_python_implementation != 'PyPy'",
"setuptools-rust>=0.11.4",
]
build-backend = "setuptools.build_meta"
[tool.black]
line-length = 79
target-version = ["py36"]
[tool.pytest.ini_options]
addopts = "-r s --capture=no --strict-markers --benchmark-disable"
markers = [
"skip_fips: this test is not executed in FIPS mode",
"supported: parametrized test requiring only_if and skip_message",
]
[tool.mypy]
show_error_codes = true
check_untyped_defs = true
no_implicit_reexport = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_unused_configs = true
strict_equality = true
[[tool.mypy.overrides]]
module = [
"pretend"
]
ignore_missing_imports = true
[tool.coverage.run]
branch = true
relative_files = true
source = [
"cryptography",
"tests/",
]
[tool.coverage.paths]
source = [
"src/cryptography",
"*.tox/*/lib*/python*/site-packages/cryptography",
"*.tox\\*\\Lib\\site-packages\\cryptography",
"*.tox/pypy/site-packages/cryptography",
]
tests =[
"tests/",
"*tests\\",
]
[tool.coverage.report]
exclude_lines = [
"@abc.abstractmethod",
"@abc.abstractproperty",
"@typing.overload",
"if typing.TYPE_CHECKING",
]

View File

@@ -0,0 +1,91 @@
[metadata]
name = cryptography
version = attr: cryptography.__version__
description = cryptography is a package which provides cryptographic recipes and primitives to Python developers.
long_description = file: README.rst
long_description_content_type = text/x-rst
license = BSD-3-Clause OR Apache-2.0
url = https://github.com/pyca/cryptography
author = The Python Cryptographic Authority and individual contributors
author_email = cryptography-dev@python.org
project_urls =
Documentation=https://cryptography.io/
Source=https://github.com/pyca/cryptography/
Issues=https://github.com/pyca/cryptography/issues
Changelog=https://cryptography.io/en/latest/changelog/
classifiers =
Development Status :: 5 - Production/Stable
Intended Audience :: Developers
License :: OSI Approved :: Apache Software License
License :: OSI Approved :: BSD License
Natural Language :: English
Operating System :: MacOS :: MacOS X
Operating System :: POSIX
Operating System :: POSIX :: BSD
Operating System :: POSIX :: Linux
Operating System :: Microsoft :: Windows
Programming Language :: Python
Programming Language :: Python :: 3
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Programming Language :: Python :: Implementation :: CPython
Programming Language :: Python :: Implementation :: PyPy
Topic :: Security :: Cryptography
[options]
python_requires = >=3.6
include_package_data = True
zip_safe = False
package_dir =
=src
packages = find:
# `install_requires` must be kept in sync with `pyproject.toml`
install_requires =
cffi >=1.12
[options.packages.find]
where = src
exclude =
_cffi_src
_cffi_src.*
[options.extras_require]
test =
pytest>=6.2.0
pytest-benchmark
pytest-cov
pytest-subtests
pytest-xdist
pretend
iso8601
pytz
hypothesis>=1.11.4,!=3.79.2
docs =
sphinx >= 1.6.5,!=1.8.0,!=3.1.0,!=3.1.1,!=5.2.0,!=5.2.0.post0
sphinx_rtd_theme
docstest =
pyenchant >= 1.6.11
twine >= 1.12.0
sphinxcontrib-spelling >= 4.0.1
sdist =
setuptools_rust >= 0.11.4
pep8test =
black
flake8
flake8-import-order
pep8-naming
# This extra is for OpenSSH private keys that use bcrypt KDF
# Versions: v3.1.3 - ignore_few_rounds, v3.1.5 - abi3
ssh =
bcrypt >= 3.1.5
[flake8]
ignore = E203,E211,W503,W504,N818
exclude = .tox,*.egg,.git,_build,.hypothesis
select = E,W,F,N,I
application-import-names = cryptography,cryptography_vectors,tests

View File

@@ -0,0 +1,19 @@
[flake8]
# Ignore style and complexity
# E: style errors
# W: style warnings
# C: complexity
# D: docstring warnings (unused pydocstyle extension)
# F841: local variable assigned but never used
ignore = E, C, W, D, F841
builtins = c, get_config
exclude =
.cache,
.github,
docs,
jupyterhub/alembic*,
onbuild,
scripts,
share,
tools,
setup.py

View File

@@ -0,0 +1,43 @@
[flake8]
# Exclude the grpc generated code
exclude = ./manim/grpc/gen/*
max-complexity = 15
max-line-length = 88
statistics = True
# Prevents some flake8-rst-docstrings errors
rst-roles = attr,class,func,meth,mod,obj,ref,doc,exc
rst-directives = manim, SEEALSO, seealso
docstring-convention=numpy
select = A,A00,B,B9,C4,C90,D,E,F,F,PT,RST,SIM,W
# General Compatibility
extend-ignore = E203, W503, D202, D212, D213, D404
# Misc
F401, F403, F405, F841, E501, E731, E402, F811, F821,
# Plug-in: flake8-builtins
A001, A002, A003,
# Plug-in: flake8-bugbear
B006, B007, B008, B009, B010, B903, B950,
# Plug-in: flake8-simplify
SIM105, SIM106, SIM119,
# Plug-in: flake8-comprehensions
C901
# Plug-in: flake8-pytest-style
PT001, PT004, PT006, PT011, PT018, PT022, PT023,
# Plug-in: flake8-docstrings
D100, D101, D102, D103, D104, D105, D106, D107,
D200, D202, D204, D205, D209,
D301,
D400, D401, D402, D403, D405, D406, D407, D409, D411, D412, D414,
# Plug-in: flake8-rst-docstrings
RST201, RST203, RST210, RST212, RST213, RST215,
RST301, RST303,

View File

@@ -12,6 +12,7 @@ classifiers = [
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3 :: Only",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Software Development :: Quality Assurance",

View File

@@ -1,16 +0,0 @@
#![allow(
clippy::collapsible_else_if,
clippy::collapsible_if,
clippy::implicit_hasher,
clippy::match_same_arms,
clippy::missing_errors_doc,
clippy::missing_panics_doc,
clippy::module_name_repetitions,
clippy::must_use_candidate,
clippy::similar_names,
clippy::too_many_lines
)]
pub mod converter;
mod parser;
pub mod plugin;

View File

@@ -1,4 +1,4 @@
//! Utility to generate Ruff's pyproject.toml section from a Flake8 INI file.
//! Utility to generate Ruff's `pyproject.toml` section from a Flake8 INI file.
#![allow(
clippy::collapsible_else_if,
clippy::collapsible_if,
@@ -11,14 +11,14 @@
clippy::similar_names,
clippy::too_many_lines
)]
#![forbid(unsafe_code)]
use std::path::PathBuf;
use anyhow::Result;
use clap::Parser;
use configparser::ini::Ini;
use flake8_to_ruff::converter;
use flake8_to_ruff::plugin::Plugin;
use ruff::flake8_to_ruff;
#[derive(Parser)]
#[command(
@@ -26,13 +26,17 @@ use flake8_to_ruff::plugin::Plugin;
long_about = None
)]
struct Cli {
/// Path to the Flake8 configuration file (e.g., 'setup.cfg', 'tox.ini', or
/// '.flake8').
/// Path to the Flake8 configuration file (e.g., `setup.cfg`, `tox.ini`, or
/// `.flake8`).
#[arg(required = true)]
file: PathBuf,
/// Optional path to a `pyproject.toml` file, used to ensure compatibility
/// with Black.
#[arg(long)]
pyproject: Option<PathBuf>,
/// List of plugins to enable.
#[arg(long, value_delimiter = ',')]
plugin: Option<Vec<Plugin>>,
plugin: Option<Vec<flake8_to_ruff::Plugin>>,
}
fn main() -> Result<()> {
@@ -43,14 +47,16 @@ fn main() -> Result<()> {
ini.set_multiline(true);
let config = ini.load(cli.file).map_err(|msg| anyhow::anyhow!(msg))?;
// Extract the Flake8 section.
let flake8 = config
.get("flake8")
.expect("Unable to find flake8 section in INI file");
// Read the pyproject.toml file.
let black = cli
.pyproject
.map(flake8_to_ruff::parse_black_options)
.transpose()?
.flatten();
// Create the pyproject.toml.
let pyproject = converter::convert(flake8, cli.plugin)?;
println!("{}", toml::to_string_pretty(&pyproject)?);
// Create Ruff's pyproject.toml section.
let pyproject = flake8_to_ruff::convert(&config, black.as_ref(), cli.plugin)?;
println!("{}", toml_edit::easy::to_string_pretty(&pyproject)?);
Ok(())
}

View File

@@ -1,455 +0,0 @@
use std::collections::{BTreeSet, HashMap};
use std::str::FromStr;
use anyhow::anyhow;
use ruff::checks_gen::CheckCodePrefix;
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub enum Plugin {
Flake8Annotations,
Flake8Bandit,
Flake8BlindExcept,
Flake8Bugbear,
Flake8Builtins,
Flake8Comprehensions,
Flake8Debugger,
Flake8Docstrings,
Flake8Eradicate,
Flake8Print,
Flake8Quotes,
Flake8Return,
Flake8TidyImports,
McCabe,
PEP8Naming,
Pyupgrade,
}
impl FromStr for Plugin {
type Err = anyhow::Error;
fn from_str(string: &str) -> Result<Self, Self::Err> {
match string {
"flake8-annotations" => Ok(Plugin::Flake8Annotations),
"flake8-bandit" => Ok(Plugin::Flake8Bandit),
"flake8-blind-except" => Ok(Plugin::Flake8BlindExcept),
"flake8-bugbear" => Ok(Plugin::Flake8Bugbear),
"flake8-builtins" => Ok(Plugin::Flake8Builtins),
"flake8-comprehensions" => Ok(Plugin::Flake8Comprehensions),
"flake8-debugger" => Ok(Plugin::Flake8Debugger),
"flake8-docstrings" => Ok(Plugin::Flake8Docstrings),
"flake8-eradicate" => Ok(Plugin::Flake8BlindExcept),
"flake8-print" => Ok(Plugin::Flake8Print),
"flake8-quotes" => Ok(Plugin::Flake8Quotes),
"flake8-return" => Ok(Plugin::Flake8Return),
"flake8-tidy-imports" => Ok(Plugin::Flake8TidyImports),
"mccabe" => Ok(Plugin::McCabe),
"pep8-naming" => Ok(Plugin::PEP8Naming),
"pyupgrade" => Ok(Plugin::Pyupgrade),
_ => Err(anyhow!("Unknown plugin: {string}")),
}
}
}
impl Plugin {
pub fn default(&self) -> CheckCodePrefix {
match self {
Plugin::Flake8Annotations => CheckCodePrefix::ANN,
Plugin::Flake8Bandit => CheckCodePrefix::S,
Plugin::Flake8BlindExcept => CheckCodePrefix::BLE,
Plugin::Flake8Bugbear => CheckCodePrefix::B,
Plugin::Flake8Builtins => CheckCodePrefix::A,
Plugin::Flake8Comprehensions => CheckCodePrefix::C4,
Plugin::Flake8Debugger => CheckCodePrefix::T1,
Plugin::Flake8Docstrings => CheckCodePrefix::D,
Plugin::Flake8Eradicate => CheckCodePrefix::ERA,
Plugin::Flake8Print => CheckCodePrefix::T2,
Plugin::Flake8Quotes => CheckCodePrefix::Q,
Plugin::Flake8Return => CheckCodePrefix::RET,
Plugin::Flake8TidyImports => CheckCodePrefix::I25,
Plugin::McCabe => CheckCodePrefix::C9,
Plugin::PEP8Naming => CheckCodePrefix::N,
Plugin::Pyupgrade => CheckCodePrefix::U,
}
}
pub fn select(&self, flake8: &HashMap<String, Option<String>>) -> Vec<CheckCodePrefix> {
match self {
Plugin::Flake8Annotations => vec![CheckCodePrefix::ANN],
Plugin::Flake8Bandit => vec![CheckCodePrefix::S],
Plugin::Flake8BlindExcept => vec![CheckCodePrefix::BLE],
Plugin::Flake8Bugbear => vec![CheckCodePrefix::B],
Plugin::Flake8Builtins => vec![CheckCodePrefix::A],
Plugin::Flake8Comprehensions => vec![CheckCodePrefix::C4],
Plugin::Flake8Debugger => vec![CheckCodePrefix::T1],
Plugin::Flake8Docstrings => {
// Use the user-provided docstring.
for key in ["docstring-convention", "docstring_convention"] {
if let Some(Some(value)) = flake8.get(key) {
match DocstringConvention::from_str(value) {
Ok(convention) => return convention.select(),
Err(e) => {
eprintln!("Unexpected '{key}' value: {value} ({e}");
return vec![];
}
}
}
}
// Default to PEP8.
DocstringConvention::PEP8.select()
}
Plugin::Flake8Eradicate => vec![CheckCodePrefix::ERA],
Plugin::Flake8Print => vec![CheckCodePrefix::T2],
Plugin::Flake8Quotes => vec![CheckCodePrefix::Q],
Plugin::Flake8Return => vec![CheckCodePrefix::RET],
Plugin::Flake8TidyImports => vec![CheckCodePrefix::I25],
Plugin::McCabe => vec![CheckCodePrefix::C9],
Plugin::PEP8Naming => vec![CheckCodePrefix::N],
Plugin::Pyupgrade => vec![CheckCodePrefix::U],
}
}
}
pub enum DocstringConvention {
All,
PEP8,
NumPy,
Google,
}
impl FromStr for DocstringConvention {
type Err = anyhow::Error;
fn from_str(string: &str) -> Result<Self, Self::Err> {
match string {
"all" => Ok(DocstringConvention::All),
"pep8" => Ok(DocstringConvention::PEP8),
"numpy" => Ok(DocstringConvention::NumPy),
"google" => Ok(DocstringConvention::Google),
_ => Err(anyhow!("Unknown docstring convention: {string}")),
}
}
}
impl DocstringConvention {
fn select(&self) -> Vec<CheckCodePrefix> {
match self {
DocstringConvention::All => vec![CheckCodePrefix::D],
DocstringConvention::PEP8 => vec![
// All errors except D203, D212, D213, D214, D215, D404, D405, D406, D407, D408,
// D409, D410, D411, D413, D415, D416 and D417.
CheckCodePrefix::D100,
CheckCodePrefix::D101,
CheckCodePrefix::D102,
CheckCodePrefix::D103,
CheckCodePrefix::D104,
CheckCodePrefix::D105,
CheckCodePrefix::D106,
CheckCodePrefix::D107,
CheckCodePrefix::D200,
CheckCodePrefix::D201,
CheckCodePrefix::D202,
// CheckCodePrefix::D203,
CheckCodePrefix::D204,
CheckCodePrefix::D205,
CheckCodePrefix::D206,
CheckCodePrefix::D207,
CheckCodePrefix::D208,
CheckCodePrefix::D209,
CheckCodePrefix::D210,
CheckCodePrefix::D211,
// CheckCodePrefix::D212,
// CheckCodePrefix::D213,
// CheckCodePrefix::D214,
// CheckCodePrefix::D215,
CheckCodePrefix::D300,
CheckCodePrefix::D400,
CheckCodePrefix::D402,
CheckCodePrefix::D403,
// CheckCodePrefix::D404,
// CheckCodePrefix::D405,
// CheckCodePrefix::D406,
// CheckCodePrefix::D407,
// CheckCodePrefix::D408,
// CheckCodePrefix::D409,
// CheckCodePrefix::D410,
// CheckCodePrefix::D411,
CheckCodePrefix::D412,
// CheckCodePrefix::D413,
CheckCodePrefix::D414,
// CheckCodePrefix::D415,
// CheckCodePrefix::D416,
// CheckCodePrefix::D417,
CheckCodePrefix::D418,
CheckCodePrefix::D419,
],
DocstringConvention::NumPy => vec![
// All errors except D107, D203, D212, D213, D402, D413, D415, D416, and D417.
CheckCodePrefix::D100,
CheckCodePrefix::D101,
CheckCodePrefix::D102,
CheckCodePrefix::D103,
CheckCodePrefix::D104,
CheckCodePrefix::D105,
CheckCodePrefix::D106,
// CheckCodePrefix::D107,
CheckCodePrefix::D200,
CheckCodePrefix::D201,
CheckCodePrefix::D202,
// CheckCodePrefix::D203,
CheckCodePrefix::D204,
CheckCodePrefix::D205,
CheckCodePrefix::D206,
CheckCodePrefix::D207,
CheckCodePrefix::D208,
CheckCodePrefix::D209,
CheckCodePrefix::D210,
CheckCodePrefix::D211,
// CheckCodePrefix::D212,
// CheckCodePrefix::D213,
CheckCodePrefix::D214,
CheckCodePrefix::D215,
CheckCodePrefix::D300,
CheckCodePrefix::D400,
// CheckCodePrefix::D402,
CheckCodePrefix::D403,
CheckCodePrefix::D404,
CheckCodePrefix::D405,
CheckCodePrefix::D406,
CheckCodePrefix::D407,
CheckCodePrefix::D408,
CheckCodePrefix::D409,
CheckCodePrefix::D410,
CheckCodePrefix::D411,
CheckCodePrefix::D412,
// CheckCodePrefix::D413,
CheckCodePrefix::D414,
// CheckCodePrefix::D415,
// CheckCodePrefix::D416,
// CheckCodePrefix::D417,
CheckCodePrefix::D418,
CheckCodePrefix::D419,
],
DocstringConvention::Google => vec![
// All errors except D203, D204, D213, D215, D400, D401, D404, D406, D407, D408,
// D409 and D413.
CheckCodePrefix::D100,
CheckCodePrefix::D101,
CheckCodePrefix::D102,
CheckCodePrefix::D103,
CheckCodePrefix::D104,
CheckCodePrefix::D105,
CheckCodePrefix::D106,
CheckCodePrefix::D107,
CheckCodePrefix::D200,
CheckCodePrefix::D201,
CheckCodePrefix::D202,
// CheckCodePrefix::D203,
// CheckCodePrefix::D204,
CheckCodePrefix::D205,
CheckCodePrefix::D206,
CheckCodePrefix::D207,
CheckCodePrefix::D208,
CheckCodePrefix::D209,
CheckCodePrefix::D210,
CheckCodePrefix::D211,
CheckCodePrefix::D212,
// CheckCodePrefix::D213,
CheckCodePrefix::D214,
// CheckCodePrefix::D215,
CheckCodePrefix::D300,
// CheckCodePrefix::D400,
CheckCodePrefix::D402,
CheckCodePrefix::D403,
// CheckCodePrefix::D404,
CheckCodePrefix::D405,
// CheckCodePrefix::D406,
// CheckCodePrefix::D407,
// CheckCodePrefix::D408,
// CheckCodePrefix::D409,
CheckCodePrefix::D410,
CheckCodePrefix::D411,
CheckCodePrefix::D412,
// CheckCodePrefix::D413,
CheckCodePrefix::D414,
CheckCodePrefix::D415,
CheckCodePrefix::D416,
CheckCodePrefix::D417,
CheckCodePrefix::D418,
CheckCodePrefix::D419,
],
}
}
}
/// Infer the enabled plugins based on user-provided options.
///
/// For example, if the user specified a `mypy-init-return` setting, we should
/// infer that `flake8-annotations` is active.
pub fn infer_plugins_from_options(flake8: &HashMap<String, Option<String>>) -> Vec<Plugin> {
let mut plugins = BTreeSet::new();
for key in flake8.keys() {
match key.as_str() {
// flake8-annotations
"suppress-none-returning" | "suppress_none_returning" => {
plugins.insert(Plugin::Flake8Annotations);
}
"suppress-dummy-args" | "suppress_dummy_args" => {
plugins.insert(Plugin::Flake8Annotations);
}
"allow-untyped-defs" | "allow_untyped_defs" => {
plugins.insert(Plugin::Flake8Annotations);
}
"allow-untyped-nested" | "allow_untyped_nested" => {
plugins.insert(Plugin::Flake8Annotations);
}
"mypy-init-return" | "mypy_init_return" => {
plugins.insert(Plugin::Flake8Annotations);
}
"dispatch-decorators" | "dispatch_decorators" => {
plugins.insert(Plugin::Flake8Annotations);
}
"overload-decorators" | "overload_decorators" => {
plugins.insert(Plugin::Flake8Annotations);
}
"allow-star-arg-any" | "allow_star_arg_any" => {
plugins.insert(Plugin::Flake8Annotations);
}
// flake8-bugbear
"extend-immutable-calls" | "extend_immutable_calls" => {
plugins.insert(Plugin::Flake8Bugbear);
}
// flake8-builtins
"builtins-ignorelist" | "builtins_ignorelist" => {
plugins.insert(Plugin::Flake8Builtins);
}
// flake8-docstrings
"docstring-convention" | "docstring_convention" => {
plugins.insert(Plugin::Flake8Docstrings);
}
// flake8-eradicate
"eradicate-aggressive" | "eradicate_aggressive" => {
plugins.insert(Plugin::Flake8Eradicate);
}
"eradicate-whitelist" | "eradicate_whitelist" => {
plugins.insert(Plugin::Flake8Eradicate);
}
"eradicate-whitelist-extend" | "eradicate_whitelist_extend" => {
plugins.insert(Plugin::Flake8Eradicate);
}
// flake8-quotes
"quotes" | "inline-quotes" | "inline_quotes" => {
plugins.insert(Plugin::Flake8Quotes);
}
"multiline-quotes" | "multiline_quotes" => {
plugins.insert(Plugin::Flake8Quotes);
}
"docstring-quotes" | "docstring_quotes" => {
plugins.insert(Plugin::Flake8Quotes);
}
"avoid-escape" | "avoid_escape" => {
plugins.insert(Plugin::Flake8Quotes);
}
// flake8-tidy-imports
"ban-relative-imports" | "ban_relative_imports" => {
plugins.insert(Plugin::Flake8TidyImports);
}
"banned-modules" | "banned_modules" => {
plugins.insert(Plugin::Flake8TidyImports);
}
// mccabe
"max-complexity" | "max_complexity" => {
plugins.insert(Plugin::McCabe);
}
// pep8-naming
"ignore-names" | "ignore_names" => {
plugins.insert(Plugin::PEP8Naming);
}
"classmethod-decorators" | "classmethod_decorators" => {
plugins.insert(Plugin::PEP8Naming);
}
"staticmethod-decorators" | "staticmethod_decorators" => {
plugins.insert(Plugin::PEP8Naming);
}
_ => {}
}
}
Vec::from_iter(plugins)
}
/// Infer the enabled plugins based on the referenced prefixes.
///
/// For example, if the user ignores `ANN101`, we should infer that
/// `flake8-annotations` is active.
pub fn infer_plugins_from_codes(codes: &BTreeSet<CheckCodePrefix>) -> Vec<Plugin> {
[
Plugin::Flake8Annotations,
Plugin::Flake8Bandit,
Plugin::Flake8BlindExcept,
Plugin::Flake8Bugbear,
Plugin::Flake8Builtins,
Plugin::Flake8Comprehensions,
Plugin::Flake8Debugger,
Plugin::Flake8Docstrings,
Plugin::Flake8Eradicate,
Plugin::Flake8Print,
Plugin::Flake8Quotes,
Plugin::Flake8Return,
Plugin::Flake8TidyImports,
Plugin::PEP8Naming,
Plugin::Pyupgrade,
]
.into_iter()
.filter(|plugin| {
for prefix in codes {
if prefix
.codes()
.iter()
.any(|code| plugin.default().codes().contains(code))
{
return true;
}
}
false
})
.collect()
}
/// Resolve the set of enabled `CheckCodePrefix` values for the given plugins.
pub fn resolve_select(
flake8: &HashMap<String, Option<String>>,
plugins: &[Plugin],
) -> BTreeSet<CheckCodePrefix> {
// Include default Pyflakes and pycodestyle checks.
let mut select = BTreeSet::from([CheckCodePrefix::E, CheckCodePrefix::F, CheckCodePrefix::W]);
// Add prefix codes for every plugin.
for plugin in plugins {
select.extend(plugin.select(flake8));
}
select
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use crate::plugin::{infer_plugins_from_options, Plugin};
#[test]
fn it_infers_plugins() {
let actual = infer_plugins_from_options(&HashMap::from([(
"inline-quotes".to_string(),
Some("single".to_string()),
)]));
let expected = vec![Plugin::Flake8Quotes];
assert_eq!(actual, expected);
let actual = infer_plugins_from_options(&HashMap::from([(
"staticmethod-decorators".to_string(),
Some("[]".to_string()),
)]));
let expected = vec![Plugin::PEP8Naming];
assert_eq!(actual, expected);
}
}

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2016 Joseph Kahn
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Martin Thoma
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,19 @@
Copyright (C) 2012-2018 Steven Myint
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,22 @@
== Flake8 License (MIT) ==
Copyright (C) 2011-2013 Tarek Ziade <tarek@ziade.org>
Copyright (C) 2012-2016 Ian Cordasco <graffatcolmingov@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 Łukasz Langa
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,45 @@
The MIT License (MIT)
Copyright (c) 2017 Thomas Grainger.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Portions of this flake8-commas Software may utilize the following
copyrighted material, the use of which is hereby acknowledged.
Original flake8-commas: https://github.com/trevorcreech/flake8-commas/commit/e8563b71b1d5442e102c8734c11cb5202284293d
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2013 Timothy Edmund Crosley
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,23 @@
Copyright © 2013 Florent Xicluna <florent.xicluna@gmail.com>
Licensed under the terms of the Expat License
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,25 @@
Copyright © 2006-2009 Johann C. Rocholl <johann@rocholl.net>
Copyright © 2009-2014 Florent Xicluna <florent.xicluna@gmail.com>
Copyright © 2014-2020 Ian Lee <IanLee1521@gmail.com>
Licensed under the terms of the Expat License
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,23 @@
Copyright (c) 2012 GreenSteam, <http://greensteam.dk/>
Copyright (c) 2014-2020 Amir Rachum, <http://amir.rachum.com/>
Copyright (c) 2020 Sambhav Kothari, <https://github.com/samj1912>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,21 @@
Copyright 2005-2011 Divmod, Inc.
Copyright 2013-2014 Florent Xicluna
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 RustPython Team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Adam Johnson
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Adam Johnson
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Adam Johnson
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Afonasev Evgeniy
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,19 @@
Copyright (c) 2019 Anthony Sottile
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,19 @@
Copyright (c) 2017 Anthony Sottile
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2014 Elijah Andrews
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2019 Dylan Turner
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2016 Joseph Kahn
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 João Palmeiro
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Nathan Hoad
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,19 @@
Copyright (c) 2018 Anthony Sottile
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 - Present S. Co1
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,19 @@
Copyright (c) 2017 Tyler Wince
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Nikita Sobolev
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,17 @@
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

25
playground/.eslintrc Normal file
View File

@@ -0,0 +1,25 @@
{
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint", "prettier"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react/recommended",
"plugin:react/jsx-runtime",
"plugin:react-hooks/recommended",
"plugin:import/recommended",
"plugin:import/typescript",
"plugin:prettier/recommended"
],
"rules": {
// Disable some recommended rules that we don't want to enforce.
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-empty-function": "off"
},
"settings": {
"react": {
"version": "detect"
}
}
}

130
playground/.gitignore vendored Normal file
View File

@@ -0,0 +1,130 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

View File

@@ -0,0 +1,3 @@
{
"trailingComma": "all"
}

14
playground/README.md Normal file
View File

@@ -0,0 +1,14 @@
# playground
In-browser playground for Ruff. Available [https://ruff.pages.dev/](https://ruff.pages.dev/).
## Getting started
- To build the WASM module, run `wasm-pack build --target web --out-dir playground/src/pkg` from the
root directory.
- Install TypeScript dependencies with: `npm install`.
- Start the development server with: `npm run dev`.
## Implementation
Design based on [Tailwind Play](https://play.tailwindcss.com/). Themed with [`ayu`](https://github.com/dempfi/ayu).

22
playground/index.html Normal file
View File

@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="description"
content="An in-browser playground for Ruff, an extremely fast Python linter written in Rust."
/>
<meta name="keywords" content="ruff, python, rust, webassembly, wasm" />
<title>Ruff Playground</title>
<link
rel="icon"
href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>⚡</text></svg>"
/>
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

6785
playground/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

42
playground/package.json Normal file
View File

@@ -0,0 +1,42 @@
{
"name": "playground",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"build": "tsc && vite build",
"check": "npm run lint && npm run tsc",
"dev": "vite",
"fmt": "prettier --cache -w .",
"lint": "eslint --cache --ext .ts,.tsx src",
"preview": "vite preview",
"tsc": "tsc"
},
"dependencies": {
"@monaco-editor/react": "^4.4.6",
"classnames": "^2.3.2",
"lz-string": "^1.4.4",
"monaco-editor": "^0.34.1",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.9",
"@typescript-eslint/eslint-plugin": "^5.47.1",
"@typescript-eslint/parser": "^5.47.1",
"@vitejs/plugin-react-swc": "^3.0.0",
"autoprefixer": "^10.4.13",
"eslint": "^8.30.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.31.11",
"eslint-plugin-react-hooks": "^4.6.0",
"postcss": "^8.4.20",
"prettier": "^2.8.1",
"tailwindcss": "^3.2.4",
"typescript": "^4.9.3",
"vite": "^4.0.0"
}
}

View File

@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

View File

@@ -0,0 +1,156 @@
import { useCallback, useEffect, useState } from "react";
import { DEFAULT_PYTHON_SOURCE } from "../constants";
import init, {
check,
Diagnostic,
currentVersion,
defaultSettings,
} from "../pkg";
import { ErrorMessage } from "./ErrorMessage";
import Header from "./Header";
import { useTheme } from "./theme";
import { persist, restore, stringify } from "./settings";
import SettingsEditor from "./SettingsEditor";
import SourceEditor from "./SourceEditor";
import MonacoThemes from "./MonacoThemes";
type Tab = "Source" | "Settings";
export default function Editor() {
const [initialized, setInitialized] = useState<boolean>(false);
const [version, setVersion] = useState<string | null>(null);
const [tab, setTab] = useState<Tab>("Source");
const [edit, setEdit] = useState<number>(0);
const [settingsSource, setSettingsSource] = useState<string | null>(null);
const [pythonSource, setPythonSource] = useState<string | null>(null);
const [diagnostics, setDiagnostics] = useState<Diagnostic[]>([]);
const [error, setError] = useState<string | null>(null);
const [theme, setTheme] = useTheme();
useEffect(() => {
init().then(() => setInitialized(true));
}, []);
useEffect(() => {
if (!initialized || settingsSource == null || pythonSource == null) {
return;
}
let config: any;
let diagnostics: Diagnostic[];
try {
config = JSON.parse(settingsSource);
} catch (e) {
setDiagnostics([]);
setError((e as Error).message);
return;
}
try {
diagnostics = check(pythonSource, config);
} catch (e) {
setError(e as string);
return;
}
setError(null);
setDiagnostics(diagnostics);
}, [initialized, settingsSource, pythonSource]);
useEffect(() => {
if (!initialized) {
return;
}
if (settingsSource == null || pythonSource == null) {
const payload = restore();
if (payload) {
const [settingsSource, pythonSource] = payload;
setSettingsSource(settingsSource);
setPythonSource(pythonSource);
} else {
setSettingsSource(stringify(defaultSettings()));
setPythonSource(DEFAULT_PYTHON_SOURCE);
}
}
}, [initialized, settingsSource, pythonSource]);
useEffect(() => {
if (!initialized) {
return;
}
setVersion(currentVersion());
}, [initialized]);
const handleShare = useCallback(() => {
if (!initialized || settingsSource == null || pythonSource == null) {
return;
}
persist(settingsSource, pythonSource);
}, [initialized, settingsSource, pythonSource]);
const handlePythonSourceChange = useCallback((pythonSource: string) => {
setEdit((edit) => edit + 1);
setPythonSource(pythonSource);
}, []);
const handleSettingsSourceChange = useCallback((settingsSource: string) => {
setEdit((edit) => edit + 1);
setSettingsSource(settingsSource);
}, []);
return (
<main
className={
"h-full w-full flex flex-auto bg-ayu-background dark:bg-ayu-background-dark"
}
>
<Header
edit={edit}
tab={tab}
theme={theme}
version={version}
onChangeTab={setTab}
onChangeTheme={setTheme}
onShare={initialized ? handleShare : undefined}
/>
<MonacoThemes />
<div className={"mt-12 relative flex-auto"}>
{initialized && settingsSource != null && pythonSource != null ? (
<>
<SourceEditor
visible={tab === "Source"}
source={pythonSource}
theme={theme}
diagnostics={diagnostics}
onChange={handlePythonSourceChange}
/>
<SettingsEditor
visible={tab === "Settings"}
source={settingsSource}
theme={theme}
onChange={handleSettingsSourceChange}
/>
</>
) : null}
</div>
{error && tab === "Source" ? (
<div
style={{
position: "fixed",
left: "10%",
right: "10%",
bottom: "10%",
}}
>
<ErrorMessage>{error}</ErrorMessage>
</div>
) : null}
</main>
);
}

View File

@@ -0,0 +1,26 @@
function truncate(str: string, length: number) {
if (str.length > length) {
return str.slice(0, length) + "...";
} else {
return str;
}
}
export function ErrorMessage({ children }: { children: string }) {
return (
<div
className="bg-orange-100 border-l-4 border-orange-500 text-orange-700 p-4"
role="alert"
>
<p className="font-bold">Error</p>
<p className="block sm:inline">
{truncate(
children.startsWith("Error: ")
? children.slice("Error: ".length)
: children,
120,
)}
</p>
</div>
);
}

View File

@@ -0,0 +1,105 @@
import classNames from "classnames";
import RepoButton from "./RepoButton";
import ThemeButton from "./ThemeButton";
import ShareButton from "./ShareButton";
import { Theme } from "./theme";
import VersionTag from "./VersionTag";
export type Tab = "Source" | "Settings";
export default function Header({
edit,
tab,
theme,
version,
onChangeTab,
onChangeTheme,
onShare,
}: {
edit: number;
tab: Tab;
theme: Theme;
version: string | null;
onChangeTab: (tab: Tab) => void;
onChangeTheme: (theme: Theme) => void;
onShare?: () => void;
}) {
return (
<div
className={classNames(
"w-full",
"flex",
"items-center",
"justify-between",
"flex-none",
"pl-5",
"sm:pl-6",
"pr-4",
"lg:pr-6",
"absolute",
"z-10",
"top-0",
"left-0",
"-mb-px",
"antialiased",
"border-b",
"border-gray-200",
"dark:border-gray-800",
)}
>
<div className="flex space-x-5">
<button
type="button"
className={classNames(
"relative flex py-3 text-sm leading-6 font-semibold focus:outline-none",
tab === "Source"
? "text-ayu-accent"
: "text-gray-700 hover:text-gray-900 focus:text-gray-900 dark:text-gray-300 dark:hover:text-white",
)}
onClick={() => onChangeTab("Source")}
>
<span
className={classNames(
"absolute bottom-0 inset-x-0 bg-ayu-accent h-0.5 rounded-full transition-opacity duration-150",
tab === "Source" ? "opacity-100" : "opacity-0",
)}
/>
Source
</button>
<button
type="button"
className={classNames(
"relative flex py-3 text-sm leading-6 font-semibold focus:outline-none",
tab === "Settings"
? "text-ayu-accent"
: "text-gray-700 hover:text-gray-900 focus:text-gray-900 dark:text-gray-300 dark:hover:text-white",
)}
onClick={() => onChangeTab("Settings")}
>
<span
className={classNames(
"absolute bottom-0 inset-x-0 bg-ayu-accent h-0.5 rounded-full transition-opacity duration-150",
tab === "Settings" ? "opacity-100" : "opacity-0",
)}
/>
Settings
</button>
</div>
<div className={"flex items-center min-w-0"}>
{version ? (
<div className={"hidden sm:flex items-center"}>
<VersionTag>v{version}</VersionTag>
</div>
) : null}
<div className="hidden sm:block mx-6 lg:mx-4 w-px h-6 bg-gray-200 dark:bg-gray-700" />
<RepoButton />
<div className="hidden sm:block mx-6 lg:mx-4 w-px h-6 bg-gray-200 dark:bg-gray-700" />
<div className="hidden sm:block">
<ShareButton key={edit} onShare={onShare} />
</div>
<div className="hidden sm:block mx-6 lg:mx-4 w-px h-6 bg-gray-200 dark:bg-gray-700" />
<ThemeButton theme={theme} onChange={onChangeTheme} />
</div>
</div>
);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
export default function RepoButton() {
return (
<a
className={"hover:text-ayu-accent/70 text-ayu-accent"}
href={"https://github.com/charliermarsh/ruff"}
target={"_blank"}
rel={"noreferrer"}
>
<svg
xmlns={"http://www.w3.org/2000/svg"}
width={"24"}
height={"24"}
viewBox={"0 0 16 16"}
fill={"none"}
>
<path
fillRule={"evenodd"}
clipRule={"evenodd"}
d={
"M8 0C3.58 0 0 3.58 0 8C0 11.54 2.29 14.53 5.47 15.59C5.87 15.66 6.02 15.42 6.02 15.21C6.02 15.02 6.01 14.39 6.01 13.72C4 14.09 3.48 13.23 3.32 12.78C3.23 12.55 2.84 11.84 2.5 11.65C2.22 11.5 1.82 11.13 2.49 11.12C3.12 11.11 3.57 11.7 3.72 11.94C4.44 13.15 5.59 12.81 6.05 12.6C6.12 12.08 6.33 11.73 6.56 11.53C4.78 11.33 2.92 10.64 2.92 7.58C2.92 6.71 3.23 5.99 3.74 5.43C3.66 5.23 3.38 4.41 3.82 3.31C3.82 3.31 4.49 3.1 6.02 4.13C6.66 3.95 7.34 3.86 8.02 3.86C8.7 3.86 9.38 3.95 10.02 4.13C11.55 3.09 12.22 3.31 12.22 3.31C12.66 4.41 12.38 5.23 12.3 5.43C12.81 5.99 13.12 6.7 13.12 7.58C13.12 10.65 11.25 11.33 9.47 11.53C9.76 11.78 10.01 12.26 10.01 13.01C10.01 14.08 10 14.94 10 15.21C10 15.42 10.15 15.67 10.55 15.59C13.71 14.53 16 11.53 16 8C16 3.58 12.42 0 8 0Z"
}
fill={"currentColor"}
/>
</svg>
</a>
);
}

View File

@@ -0,0 +1,57 @@
/**
* Editor for the settings JSON.
*/
import Editor, { useMonaco } from "@monaco-editor/react";
import { useCallback, useEffect } from "react";
import schema from "../../../ruff.schema.json";
import { Theme } from "./theme";
export default function SettingsEditor({
visible,
source,
theme,
onChange,
}: {
visible: boolean;
source: string;
theme: Theme;
onChange: (source: string) => void;
}) {
const monaco = useMonaco();
useEffect(() => {
monaco?.languages.json.jsonDefaults.setDiagnosticsOptions({
schemas: [
{
uri: "https://raw.githubusercontent.com/charliermarsh/ruff/main/ruff.schema.json",
fileMatch: ["*"],
schema,
},
],
});
}, [monaco]);
const handleChange = useCallback(
(value: string | undefined) => {
onChange(value ?? "");
},
[onChange],
);
return (
<Editor
options={{
readOnly: false,
minimap: { enabled: false },
fontSize: 14,
roundedSelection: false,
scrollBeyondLastLine: false,
}}
wrapperProps={visible ? {} : { style: { display: "none" } }}
language={"json"}
value={source}
theme={theme === "light" ? "Ayu-Light" : "Ayu-Dark"}
onChange={handleChange}
/>
);
}

View File

@@ -0,0 +1,53 @@
import { useEffect, useState } from "react";
export default function ShareButton({ onShare }: { onShare?: () => void }) {
const [copied, setCopied] = useState(false);
useEffect(() => {
if (copied) {
const timeout = setTimeout(() => setCopied(false), 2000);
return () => clearTimeout(timeout);
}
}, [copied]);
return copied ? (
<button
type="button"
className="relative flex-none rounded-md text-sm font-semibold leading-6 py-1.5 px-3 cursor-auto text-ayu-accent shadow-copied dark:bg-ayu-accent/10"
>
<span
className="absolute inset-0 flex items-center justify-center invisible"
aria-hidden="true"
>
Share
</span>
<span className="" aria-hidden="false">
Copied!
</span>
</button>
) : (
<button
type="button"
className="relative flex-none rounded-md text-sm font-semibold leading-6 py-1.5 px-3 enabled:hover:bg-ayu-accent/70 bg-ayu-accent text-white shadow-sm dark:shadow-highlight/20 disabled:opacity-50"
disabled={!onShare || copied}
onClick={
onShare
? () => {
setCopied(true);
onShare();
}
: undefined
}
>
<span
className="absolute inset-0 flex items-center justify-center"
aria-hidden="false"
>
Share
</span>
<span className="invisible" aria-hidden="true">
Copied!
</span>
</button>
);
}

View File

@@ -0,0 +1,117 @@
/**
* Editor for the Python source code.
*/
import Editor, { useMonaco } from "@monaco-editor/react";
import { MarkerSeverity, MarkerTag } from "monaco-editor";
import { useCallback, useEffect } from "react";
import { Diagnostic } from "../pkg";
import { Theme } from "./theme";
export default function SourceEditor({
visible,
source,
theme,
diagnostics,
onChange,
}: {
visible: boolean;
source: string;
diagnostics: Diagnostic[];
theme: Theme;
onChange: (pythonSource: string) => void;
}) {
const monaco = useMonaco();
useEffect(() => {
const editor = monaco?.editor;
const model = editor?.getModels()[0];
if (!editor || !model) {
return;
}
editor.setModelMarkers(
model,
"owner",
diagnostics.map((diagnostic) => ({
startLineNumber: diagnostic.location.row,
startColumn: diagnostic.location.column + 1,
endLineNumber: diagnostic.end_location.row,
endColumn: diagnostic.end_location.column + 1,
message: `${diagnostic.code}: ${diagnostic.message}`,
severity: MarkerSeverity.Error,
tags:
diagnostic.code === "F401" || diagnostic.code === "F841"
? [MarkerTag.Unnecessary]
: [],
})),
);
const codeActionProvider = monaco?.languages.registerCodeActionProvider(
"python",
{
// @ts-expect-error: The type definition is wrong.
provideCodeActions: function (model, position) {
const actions = diagnostics
.filter((check) => position.startLineNumber === check.location.row)
.filter((check) => check.fix)
.map((check) => ({
title: check.fix
? `${check.code}: ${check.fix.message}` ?? `Fix ${check.code}`
: "Autofix",
id: `fix-${check.code}`,
kind: "quickfix",
edit: check.fix
? {
edits: [
{
resource: model.uri,
versionId: model.getVersionId(),
edit: {
range: {
startLineNumber: check.fix.location.row,
startColumn: check.fix.location.column + 1,
endLineNumber: check.fix.end_location.row,
endColumn: check.fix.end_location.column + 1,
},
text: check.fix.content,
},
},
],
}
: undefined,
}));
return { actions, dispose: () => {} };
},
},
);
return () => {
codeActionProvider?.dispose();
};
}, [diagnostics, monaco]);
const handleChange = useCallback(
(value: string | undefined) => {
onChange(value ?? "");
},
[onChange],
);
return (
<Editor
options={{
readOnly: false,
minimap: { enabled: false },
fontSize: 14,
roundedSelection: false,
scrollBeyondLastLine: false,
}}
language={"python"}
wrapperProps={visible ? {} : { style: { display: "none" } }}
theme={theme === "light" ? "Ayu-Light" : "Ayu-Dark"}
value={source}
onChange={handleChange}
/>
);
}

View File

@@ -0,0 +1,49 @@
/**
* Button to toggle between light and dark mode themes.
*/
import { Theme } from "./theme";
export default function ThemeButton({
theme,
onChange,
}: {
theme: Theme;
onChange: (theme: Theme) => void;
}) {
return (
<button
type="button"
className="ml-4 sm:ml-0 ring-1 ring-gray-900/5 shadow-sm hover:bg-gray-50 dark:ring-0 dark:bg-gray-800 dark:hover:bg-gray-700 dark:shadow-highlight/4 group focus:outline-none focus-visible:ring-2 rounded-md focus-visible:ring-ayu-accent dark:focus-visible:ring-2 dark:focus-visible:ring-gray-400"
onClick={() => onChange(theme === "light" ? "dark" : "light")}
>
<span className="sr-only">
<span className="dark:hidden">Switch to dark theme</span>
<span className="hidden dark:inline">Switch to light theme</span>
</span>
<svg
width="36"
height="36"
viewBox="-6 -6 36 36"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
className="stroke-ayu-accent fill-ayu-accent/10 group-hover:stroke-ayu-accent/80 dark:stroke-gray-400 dark:fill-gray-400/20 dark:group-hover:stroke-gray-300"
>
<g className="dark:opacity-0">
<path d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"></path>
<path
d="M12 4v.01M17.66 6.345l-.007.007M20.005 12.005h-.01M17.66 17.665l-.007-.007M12 20.01V20M6.34 17.665l.007-.007M3.995 12.005h.01M6.34 6.344l.007.007"
fill="none"
/>
</g>
<g className="opacity-0 dark:opacity-100">
<path d="M16 12a4 4 0 1 1-8 0 4 4 0 0 1 8 0Z" />
<path
d="M12 3v1M18.66 5.345l-.828.828M21.005 12.005h-1M18.66 18.665l-.828-.828M12 21.01V20M5.34 18.666l.835-.836M2.995 12.005h1.01M5.34 5.344l.835.836"
fill="none"
/>
</g>
</svg>
</button>
);
}

View File

@@ -0,0 +1,26 @@
import classNames from "classnames";
import { ReactNode } from "react";
export default function VersionTag({ children }: { children: ReactNode }) {
return (
<div
className={classNames(
"text-gray-500",
"text-xs",
"leading-5",
"font-semibold",
"bg-gray-400/10",
"rounded-full",
"py-1",
"px-3",
"flex",
"items-center",
"dark:bg-gray-800",
"dark:text-gray-400",
"dark:shadow-highlight/4",
)}
>
{children}
</div>
);
}

View File

@@ -0,0 +1,3 @@
import Editor from "./Editor";
export default Editor;

View File

@@ -0,0 +1,50 @@
import lzstring from "lz-string";
export type Settings = { [K: string]: any };
/**
* Stringify a settings object to JSON.
*/
export function stringify(settings: Settings): string {
return JSON.stringify(
settings,
(k, v) => {
if (v instanceof Map) {
return Object.fromEntries(v.entries());
} else {
return v;
}
},
2,
);
}
/**
* Persist the configuration to a URL.
*/
export async function persist(settingsSource: string, pythonSource: string) {
const hash = lzstring.compressToEncodedURIComponent(
settingsSource + "$$$" + pythonSource,
);
await navigator.clipboard.writeText(
window.location.href.split("#")[0] + "#" + hash,
);
}
/**
* Restore the configuration from a URL.
*/
export function restore(): [string, string] | null {
const value = lzstring.decompressFromEncodedURIComponent(
window.location.hash.slice(1),
);
if (value) {
const parts = value.split("$$$");
const settingsSource = parts[0];
const pythonSource = parts[1];
return [settingsSource, pythonSource];
} else {
return null;
}
}

View File

@@ -0,0 +1,35 @@
/**
* Light and dark mode theming.
*/
import { useEffect, useState } from "react";
export type Theme = "dark" | "light";
export function useTheme(): [Theme, (theme: Theme) => void] {
const [localTheme, setLocalTheme] = useState<Theme>("light");
const setTheme = (mode: Theme) => {
if (mode === "dark") {
document.body.classList.add("dark");
} else {
document.body.classList.remove("dark");
}
localStorage.setItem("theme", mode);
setLocalTheme(mode);
};
useEffect(() => {
const initialTheme = localStorage.getItem("theme");
if (initialTheme === "dark") {
setTheme("dark");
} else if (initialTheme === "light") {
setTheme("light");
} else if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
setTheme("dark");
} else {
setTheme("light");
}
}, []);
return [localTheme, setTheme];
}

View File

@@ -0,0 +1,7 @@
export async function copyTextToClipboard(text: string) {
if ("clipboard" in navigator) {
return await navigator.clipboard.writeText(text);
} else {
return document.execCommand("copy", true, text);
}
}

View File

@@ -0,0 +1,31 @@
export const DEFAULT_PYTHON_SOURCE =
"import os\n" +
"\n" +
"# Define a function that takes an integer n and returns the nth number in the Fibonacci\n" +
"# sequence.\n" +
"def fibonacci(n):\n" +
' """Compute the nth number in the Fibonacci sequence."""\n' +
" x = 1\n" +
" if n == 0:\n" +
" return 0\n" +
" elif n == 1:\n" +
" return 1\n" +
" else:\n" +
" return fibonacci(n - 1) + fibonacci(n - 2)\n" +
"\n" +
"\n" +
"# Use a for loop to generate and print the first 10 numbers in the Fibonacci sequence.\n" +
"for i in range(10):\n" +
" print(fibonacci(i))\n" +
"\n" +
"# Output:\n" +
"# 0\n" +
"# 1\n" +
"# 1\n" +
"# 2\n" +
"# 3\n" +
"# 5\n" +
"# 8\n" +
"# 13\n" +
"# 21\n" +
"# 34\n";

24
playground/src/index.css Normal file
View File

@@ -0,0 +1,24 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
* {
box-sizing: border-box;
}
body,
html,
#root {
margin: 0;
height: 100%;
width: 100%;
}
.shadow-copied {
--tw-shadow: 0 0 0 1px #f07171, inset 0 0 0 1px #f07171;
--tw-shadow-colored: 0 0 0 1px var(--tw-shadow-color),
inset 0 0 0 1px var(--tw-shadow-color);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000),
var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
}

10
playground/src/main.tsx Normal file
View File

@@ -0,0 +1,10 @@
import React from "react";
import ReactDOM from "react-dom/client";
import Editor from "./Editor";
import "./index.css";
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<React.StrictMode>
<Editor />
</React.StrictMode>,
);

6
playground/src/third-party.d.ts vendored Normal file
View File

@@ -0,0 +1,6 @@
declare module "lz-string" {
function decompressFromEncodedURIComponent(
input: string | null,
): string | null;
function compressToEncodedURIComponent(input: string | null): string;
}

1
playground/src/vite-env.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
/// <reference types="vite/client" />

View File

@@ -0,0 +1,22 @@
/** @type {import('tailwindcss').Config} */
const defaultTheme = require("tailwindcss/defaultTheme");
module.exports = {
darkMode: "class",
content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"],
theme: {
extend: {
colors: {
"ayu-accent": "#fa8d3e",
"ayu-background": {
DEFAULT: "#f8f9fa",
dark: "#0b0e14",
},
},
fontFamily: {
sans: ["Inter var", ...defaultTheme.fontFamily.sans],
},
},
},
plugins: [],
};

21
playground/tsconfig.json Normal file
View File

@@ -0,0 +1,21 @@
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": false,
"skipLibCheck": true,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}

View File

@@ -0,0 +1,9 @@
{
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}

View File

@@ -0,0 +1,7 @@
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
});

View File

@@ -1,5 +1,22 @@
[build-system]
requires = ["maturin>=0.14.10,<0.15"]
# We depend on >=0.14.10 because we specify name in
# [package.metadata.maturin] in ruff_cli/Cargo.toml.
build-backend = "maturin"
[project]
name = "ruff"
version = "0.0.227"
description = "An extremely fast Python linter, written in Rust."
authors = [
{ name = "Charlie Marsh", email = "charlie.r.marsh@gmail.com" },
]
maintainers = [
{ name = "Charlie Marsh", email = "charlie.r.marsh@gmail.com" },
]
requires-python = ">=3.7"
license = { file = "LICENSE" }
keywords = ["automation", "flake8", "pycodestyle", "pyflakes", "pylint", "clippy"]
classifiers = [
"Development Status :: 3 - Alpha",
@@ -12,26 +29,15 @@ classifiers = [
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3 :: Only",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Software Development :: Quality Assurance",
]
author = "Charlie Marsh"
author_email = "charlie.r.marsh@gmail.com"
description = "An extremely fast Python linter, written in Rust."
requires-python = ">=3.7"
[project.urls]
repository = "https://github.com/charliermarsh/ruff"
[build-system]
requires = ["maturin>=0.14,<0.15"]
build-backend = "maturin"
urls = { repository = "https://github.com/charliermarsh/ruff" }
[tool.maturin]
bindings = "bin"
manifest-path = "ruff_cli/Cargo.toml"
python-source = "python"
strip = true
[tool.ruff.isort]
force-wrap-aliases = true
combine-as-imports = true

3
resources/test/fixtures/README.md vendored Normal file
View File

@@ -0,0 +1,3 @@
# fixtures
Fixture files used for snapshot testing.

View File

@@ -5,9 +5,11 @@ a = 4
#foo(1, 2, 3)
def foo(x, y, z):
contentet = 1 # print('hello')
content = 1 # print('hello')
print(x, y, z)
# This is a real comment.
#return True
return False
#import os # noqa: ERA001

View File

@@ -0,0 +1,9 @@
class C:
from typing import overload
@overload
def f(self, x: int, y: int) -> None:
...
def f(self, x, y):
pass

View File

@@ -0,0 +1,49 @@
from typing import overload
@overload
def foo(i: int) -> "int":
...
@overload
def foo(i: "str") -> "str":
...
def foo(i):
return i
@overload
def bar(i: int) -> "int":
...
@overload
def bar(i: "str") -> "str":
...
class X:
def bar(i):
return i
# TODO(charlie): This third case should raise an error (as in Mypy), because we have a
# statement between the interfaces and implementation.
@overload
def baz(i: int) -> "int":
...
@overload
def baz(i: "str") -> "str":
...
x = 1
def baz(i):
return i

View File

@@ -0,0 +1,22 @@
import os
import stat
keyfile = "foo"
os.chmod("/etc/passwd", 0o227) # Error
os.chmod("/etc/passwd", 0o7) # Error
os.chmod("/etc/passwd", 0o664) # OK
os.chmod("/etc/passwd", 0o777) # Error
os.chmod("/etc/passwd", 0o770) # Error
os.chmod("/etc/passwd", 0o776) # Error
os.chmod("/etc/passwd", 0o760) # OK
os.chmod("~/.bashrc", 511) # Error
os.chmod("/etc/hosts", 0o777) # Error
os.chmod("/tmp/oh_hai", 0x1FF) # Error
os.chmod("/etc/passwd", stat.S_IRWXU) # OK
os.chmod(keyfile, 0o777) # Error
os.chmod(keyfile, 0o7 | 0o70 | 0o700) # Error
os.chmod(keyfile, stat.S_IRWXO | stat.S_IRWXG | stat.S_IRWXU) # Error
os.chmod("~/hidden_exec", stat.S_IXGRP) # Error
os.chmod("~/hidden_exec", stat.S_IXOTH) # OK
os.chmod("/etc/passwd", stat.S_IWOTH) # Error

View File

@@ -51,3 +51,12 @@ secret == "s3cr3t"
token == "s3cr3t"
secrete == "s3cr3t"
password == safe == "s3cr3t"
if token == "1\n2":
pass
if token == "3\t4":
pass
if token == "5\r6":
pass

View File

@@ -0,0 +1,16 @@
# ok
with open("/abc/tmp", "w") as f:
f.write("def")
with open("/tmp/abc", "w") as f:
f.write("def")
with open("/var/tmp/123", "w") as f:
f.write("def")
with open("/dev/shm/unit/test", "w") as f:
f.write("def")
# not ok by config
with open("/foo/bar", "w") as f:
f.write("def")

View File

@@ -0,0 +1,23 @@
import requests
requests.get('https://gmail.com')
requests.get('https://gmail.com', timeout=None)
requests.get('https://gmail.com', timeout=5)
requests.post('https://gmail.com')
requests.post('https://gmail.com', timeout=None)
requests.post('https://gmail.com', timeout=5)
requests.put('https://gmail.com')
requests.put('https://gmail.com', timeout=None)
requests.put('https://gmail.com', timeout=5)
requests.delete('https://gmail.com')
requests.delete('https://gmail.com', timeout=None)
requests.delete('https://gmail.com', timeout=5)
requests.patch('https://gmail.com')
requests.patch('https://gmail.com', timeout=None)
requests.patch('https://gmail.com', timeout=5)
requests.options('https://gmail.com')
requests.options('https://gmail.com', timeout=None)
requests.options('https://gmail.com', timeout=5)
requests.head('https://gmail.com')
requests.head('https://gmail.com', timeout=None)
requests.head('https://gmail.com', timeout=5)

View File

@@ -0,0 +1,52 @@
import hashlib
from hashlib import new as hashlib_new
from hashlib import sha1 as hashlib_sha1
# Invalid
hashlib.new('md5')
hashlib.new('md4', b'test')
hashlib.new(name='md5', data=b'test')
hashlib.new('MD4', data=b'test')
hashlib.new('sha1')
hashlib.new('sha1', data=b'test')
hashlib.new('sha', data=b'test')
hashlib.new(name='SHA', data=b'test')
hashlib.sha(data=b'test')
hashlib.md5()
hashlib_new('sha1')
hashlib_sha1('sha1')
# usedforsecurity arg only available in Python 3.9+
hashlib.new('sha1', usedforsecurity=True)
# Valid
hashlib.new('sha256')
hashlib.new('SHA512')
hashlib.sha256(data=b'test')
# usedforsecurity arg only available in Python 3.9+
hashlib_new(name='sha1', usedforsecurity=False)
# usedforsecurity arg only available in Python 3.9+
hashlib_sha1(name='sha1', usedforsecurity=False)
# usedforsecurity arg only available in Python 3.9+
hashlib.md4(usedforsecurity=False)
# usedforsecurity arg only available in Python 3.9+
hashlib.new(name='sha256', usedforsecurity=False)

View File

@@ -0,0 +1,40 @@
import httpx
import requests
requests.get('https://gmail.com', timeout=30, verify=True)
requests.get('https://gmail.com', timeout=30, verify=False)
requests.post('https://gmail.com', timeout=30, verify=True)
requests.post('https://gmail.com', timeout=30, verify=False)
requests.put('https://gmail.com', timeout=30, verify=True)
requests.put('https://gmail.com', timeout=30, verify=False)
requests.delete('https://gmail.com', timeout=30, verify=True)
requests.delete('https://gmail.com', timeout=30, verify=False)
requests.patch('https://gmail.com', timeout=30, verify=True)
requests.patch('https://gmail.com', timeout=30, verify=False)
requests.options('https://gmail.com', timeout=30, verify=True)
requests.options('https://gmail.com', timeout=30, verify=False)
requests.head('https://gmail.com', timeout=30, verify=True)
requests.head('https://gmail.com', timeout=30, verify=False)
httpx.request('GET', 'https://gmail.com', verify=True)
httpx.request('GET', 'https://gmail.com', verify=False)
httpx.get('https://gmail.com', verify=True)
httpx.get('https://gmail.com', verify=False)
httpx.options('https://gmail.com', verify=True)
httpx.options('https://gmail.com', verify=False)
httpx.head('https://gmail.com', verify=True)
httpx.head('https://gmail.com', verify=False)
httpx.post('https://gmail.com', verify=True)
httpx.post('https://gmail.com', verify=False)
httpx.put('https://gmail.com', verify=True)
httpx.put('https://gmail.com', verify=False)
httpx.patch('https://gmail.com', verify=True)
httpx.patch('https://gmail.com', verify=False)
httpx.delete('https://gmail.com', verify=True)
httpx.delete('https://gmail.com', verify=False)
httpx.stream('https://gmail.com', verify=True)
httpx.stream('https://gmail.com', verify=False)
httpx.Client()
httpx.Client(verify=False)
httpx.AsyncClient()
httpx.AsyncClient(verify=False)

View File

@@ -0,0 +1,31 @@
import json
import yaml
from yaml import CSafeLoader
from yaml import SafeLoader
from yaml import SafeLoader as NewSafeLoader
def test_yaml_load():
ystr = yaml.dump({"a": 1, "b": 2, "c": 3})
y = yaml.load(ystr)
yaml.dump(y)
try:
y = yaml.load(ystr, Loader=yaml.CSafeLoader)
except AttributeError:
# CSafeLoader only exists if you build yaml with LibYAML
y = yaml.load(ystr, Loader=yaml.SafeLoader)
def test_json_load():
# no issue should be found
j = json.load("{}")
yaml.load("{}", Loader=yaml.Loader)
# no issue should be found
yaml.load("{}", SafeLoader)
yaml.load("{}", yaml.SafeLoader)
yaml.load("{}", CSafeLoader)
yaml.load("{}", yaml.CSafeLoader)
yaml.load("{}", NewSafeLoader)

View File

@@ -0,0 +1,6 @@
from pysnmp.hlapi import CommunityData
CommunityData("public", mpModel=0) # S508
CommunityData("public", mpModel=1) # S508
CommunityData("public", mpModel=2) # OK

Some files were not shown because too many files have changed in this diff Show More