{"id":13733888,"url":"https://github.com/robsdedude/flake8-picky-parentheses","last_synced_at":"2025-06-10T12:03:26.150Z","repository":{"id":55125328,"uuid":"522904951","full_name":"robsdedude/flake8-picky-parentheses","owner":"robsdedude","description":"flake8 plugin to check for redundant parentheses","archived":false,"fork":false,"pushed_at":"2025-01-16T15:14:44.000Z","size":181,"stargazers_count":7,"open_issues_count":3,"forks_count":3,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-06-04T15:20:42.866Z","etag":null,"topics":["flake8","flake8-plugin","hacktoberfest","lint","linter","linting","opinionated","python"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/flake8-picky-parentheses/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/robsdedude.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-08-09T10:37:12.000Z","updated_at":"2025-01-16T15:14:45.000Z","dependencies_parsed_at":"2024-01-06T09:55:06.133Z","dependency_job_id":"2858f440-ffe4-4503-8143-248738b225f5","html_url":"https://github.com/robsdedude/flake8-picky-parentheses","commit_stats":{"total_commits":160,"total_committers":4,"mean_commits":40.0,"dds":0.5375,"last_synced_commit":"6d1da7ba1b682d1c780fde31547e0bf13e3d78e7"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robsdedude%2Fflake8-picky-parentheses","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robsdedude%2Fflake8-picky-parentheses/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robsdedude%2Fflake8-picky-parentheses/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robsdedude%2Fflake8-picky-parentheses/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/robsdedude","download_url":"https://codeload.github.com/robsdedude/flake8-picky-parentheses/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robsdedude%2Fflake8-picky-parentheses/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259072603,"owners_count":22801063,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["flake8","flake8-plugin","hacktoberfest","lint","linter","linting","opinionated","python"],"created_at":"2024-08-03T03:00:50.638Z","updated_at":"2025-06-10T12:03:26.089Z","avatar_url":"https://github.com/robsdedude.png","language":"Python","funding_links":[],"categories":["Clean code"],"sub_categories":[],"readme":"Picky Parentheses\n=================\n\nPicky Parentheses is a [flake8](https://github.com/pycqa/flake8) plugin that\nnitpicks all things parentheses, brackets and braces.\nThe plugin has two components:\n 1. A checker that warns about redundant parentheses (with some exceptions).\n 2. A checker for parentheses, brackets, and braces alignment.\n    This component is very opinionated but has its own error codes so you can\n    easily disable it.\n\n\n## Table of Contents\n\n * [Installation and Usage](#installation-and-usage)\n * [Error Codes](#error-codes)\n * [Details and Exceptions](#details-and-exceptions)\n * [Additional Notes](#additional-notes)\n\n\n## Installation and Usage\nThis is a plugin for `flake8`. It supports Python 3.7 - 3.13.  \nRefer to the documentation of `flake8` on how to run it on your code:\nhttps://flake8.pycqa.org/en/latest/\n\nTwo common options are to either install the plugin and then run `flake8`:\n```bash\npip install flake8-picky-parentheses\n\nflake8 '\u003cpath/to/your/code\u003e'\n```\n\nOr to let `flake8` fetch the plugin for you (requires `flake8 \u003e= 5.0.0`):\n```bash\nflake8 --require-plugins flake8-picky-parentheses '\u003cpath/to/your/code\u003e'\n```\n\nIf you only want to run this plugin and bypass any other `flake8` checks, you\ncan use the `--select` option:\n```bash\nflake8 [other options] --select='PAR0,PAR1' '\u003cpath/to/your/code\u003e'\n```\n\nWhere `PAR0` is the code for the redundant parentheses checker and `PAR1` is\nthe code for the parentheses alignment checker.\n\nIf you, in turn want to disable the opinionated parentheses alignment checker,\nyou can use the `--ignore` or `--extend-ignore` option:\n```bash\nflake8 [other options] --extend-ignore='PAR1' '\u003cpath/to/your/code\u003e'\n```\n\n\n## Error Codes\nThese are the error codes which you can get using this plugin:\n\n| Code                | Brief Description                                                                           |\n|---------------------|---------------------------------------------------------------------------------------------|\n| [`PAR0xx`](#par0xx) | [Group] Redundant parentheses                                                               |\n| [`PAR001`](#par001) | Redundant parentheses (general)                                                             |\n| [`PAR002`](#par002) | Parentheses used for tuple unpacking                                                        |\n|                     |                                                                                             |\n| [`PAR1xx`](#par1xx) | [Group] (Opinionated) parentheses, brackets, braces not well-aligned                        |\n| [`PAR101`](#par101) | Opening bracket is last, but closing is not on new line                                     |\n| [`PAR102`](#par102) | Closing bracket has different indentation than the line with the opening bracket            |\n| [`PAR103`](#par103) | Consecutive opening brackets at the end of the line must have consecutive closing brackets. |\n| [`PAR104`](#par104) | Only operators and comments are allowed after a closing bracket on a new line               |\n\n### `PAR0xx`\nThese are the error codes for the redundant parentheses checker.\n#### `PAR001`\nIt means that you use redundant parentheses, and they do not help readability.\nFor example:\n```python\n# BAD\na = ((\"a\", \"b\"))\n```\n#### `PAR002`\nIt means that you use parentheses for an unpacking expression. For example:\n```python\n# BAD\n(a,) = \"b\"\n```\n\n#### `PAR1xx`\nThese are the error codes for the opinionated alignment checker.\n#### `PAR101`\nIt means that the opening bracket is last in its line, but closing one is not\non a new line. For example:\n```python\n# BAD\nif (\n        a == b):\n    c + d\n\n# GOOD\nif (\n    a == b\n):\n    c + d\n\n# BAD\na = [\n    1, 2,\n    3, 4]\n\n# GOOD\na = [\n    1, 2,\n    3, 4\n]\n\n# GOOD\na = [1, 2,\n     3, 4]\n```\n#### `PAR102`\nIt means that closing bracket is on new line, but there is a indentation\nmismatch. For example:\n```python\n# BAD\nif (\n    a == b\n        ):\n    c + d\n\n# GOOD\nif (\n    a == b\n):\n    c + d\n\n# BAD\na = [\n    1, 2,\n    3, 4\n    ]\n\n# GOOD\na = [\n    1, 2,\n    3, 4\n]\n```\n\n#### `PAR103`\nIt means that consecutive opening brackets at the end of a line must have\nconsecutive closing brackets.\n```python\n# BAD\nanswer = func((\n    1, 2, 3, 4, 5,\n    )\n)\n\n# GOOD\nanswer = func((\n    1, 2, 3, 4, 5,\n))\n```\n\n#### `PAR104`\nOnly operators and comments are allowed after a closing bracket on a new line.\n```python\n# BAD\na = func(\n    1, 2, 3, 4, 5\n) + 6\n\n# GOOD\na = (\n    func(\n        1, 2, 3, 4, 5\n    )\n    + 6\n)\n```\n\n\n## Details and Exceptions\n\nThe redundant parentheses checker uses Python's `tokenize` and `ast` module to\ntry to remove each pair of parentheses and see if the code still compiles and\nyields the same AST (i.e., is semantically equivalent).\nIf it does, a flake (lint error) is reported. However, there are two notable\nexceptions to this rule:\n 1. Parentheses for tuple literals.\n 2. A single pair or parentheses in expressions to highlight operator\n    precedence.\n    Even if these parentheses are redundant, they help to divide parts of\n    expressions and show sequence of actions.\n 3. Parts of slices.\n 4. Multi-line\u003csup\u003e[1)](#footnotes)\u003c/sup\u003e expression, `if` and `for` parts in comprehensions.\n 5. Multi-line\u003csup\u003e[1)](#footnotes)\u003c/sup\u003e keyword arguments or argument defaults.\n 6. String concatenation over several lines in lists, tuples, and function arguments.\n\n\nException type 1:\n```python\na = (\"a\",)     # GOOD\na = \"a\",       # GOOD\na = (\"a\")      # BAD\na = ((\"a\"),)   # BAD\na = ((\"a\",))   # BAD\nfoo((\"a\",))    # GOOD\nfoo(\"a\",)      # BAD\n```\n\nException type 2:\n```python\na = (1 + 2) + 3            # GOOD\na = (1 + 2) % 3            # GOOD\na = 1 and (2 + 3)          # GOOD\na = (1 / 2) * 3            # GOOD\na = not (1 + 2)            # GOOD\na = (not 1) + 2            # GOOD\na = 1 + (2 if a else 3)    # GOOD\na = foo(*(a if b else c))  # GOOD\na = foo(*(a + b))          # GOOD\na = foo(**(a + b))         # GOOD\na = (1 + 2)                # BAD\na = 1 + (2)                # BAD\na = ((not 1)) + 2          # BAD\na = foo(*(a))              # BAD\na = foo(**(a))             # BAD\n```\n\nException type 3:\n```python\nfoo[(1 + 2):10]    # GOOD\nfoo[1:(1 + 2)]     # GOOD\nfoo[1:5:(1 + 1)]   # GOOD\nfoo[:(-bar)]       # GOOD\nfoo[(1):]          # BAD\nfoo[:(1)]          # BAD\n```\n\nException type 4:\n```python\n# GOOD\na = (\n    b for b in c\n    if (\n        some_thing == other_thing\n        or whatever_but_long\n    )\n)\n\n# GOOD\na = [\n    b for b in c\n    if (b\n        in d)\n]\n\n# BAD\na = (\n    b for b in c\n    if (b in d)\n)\n\n# GOOD\na = (\n    b for b in (c\n                + d)\n)\n\n# BAD\na = (\n    b for b in (c + d)\n)\n\n# GOOD\na = (\n    (\n        1\n        + b\n    )\n    for b in c\n)\n\n# BAD\na = (\n    (1 + b) for b in c\n)\n\n# GOOD\na = {\n    (\n        \"foo%s\"\n        % b\n    ): (\n        b\n        * 2\n    )\n    for b in c\n}\n```\n\nException type 5:\n```python\n# GOOD\nfoo(bar=(a\n         in b))\n\n# BAD\nfoo(bar=(a in b))\n\n# GOOD\ndef foo(bar=(a\n             is b)):\n    ...\n\n# BAD\ndef foo(bar=(a is b)):\n    ...\n```\n\nException type 6:\n\n```python\n# GOOD\n[\n    \"a\",\n    (\n        \"b\"\n        \"c\"\n    ),\n    \"d\",\n]\n\n# This helps to avoid forgetting a comma at the end of a string spanning\n# multiple lines. Compare with:\n[\n    \"a\",\n    \"b\"\n    \"c\",\n    \"d\",\n]\n# Was the comma after \"b\" forgotten or was the string supposed to be \"bc\"?\n\n# BAD\n[\n    (\n        \"a\" \"b\"\n    ),\n]\n\n# This also applies to function calls:\n# GOOD\nfunc(\n    (\n        \"a\"\n        \"b\"\n    ),\n    \"c\",\n)\n```\n\n### Footnotes:\n1. Multi-line means that either\n   * the expression spans multiple lines, e.g.,\n     ```python\n     (a\n      + b)\n     ```\n   * or the first part of the expression is on a new line (e.g., if a name is very long), e.g.,\n     ```python\n     (\n         veeeeeeeeeeery_looooooong_name\n     )\n     ```\n     but also\n     ```python\n     (\n         a\n         + b\n     )\n     ```\n   Multi-line expressions do **not** include\n   ```python\n   (a + b\n   )\n   ```\n\n## Additional Notes\n\nThis plugin was developed to improve the code quality of Neo4j Python projects.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobsdedude%2Fflake8-picky-parentheses","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobsdedude%2Fflake8-picky-parentheses","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobsdedude%2Fflake8-picky-parentheses/lists"}