Skip to content

Implement chained comparison improvements and related checks#7611

Open
areveny wants to merge 24 commits into
pylint-dev:mainfrom
areveny:release-chained-comparison
Open

Implement chained comparison improvements and related checks#7611
areveny wants to merge 24 commits into
pylint-dev:mainfrom
areveny:release-chained-comparison

Conversation

@areveny

@areveny areveny commented Oct 12, 2022

Copy link
Copy Markdown
Contributor

Hi.

This PR adds improvements to chained-comparison by processing the chain of comparisons into a graph. It's still a bit unpolished but I would like some higher-level feedback on the direction.

It adds two new checks:

  1. impossible-comparison for cases when a comparison would always be false, e.g. a > b and b > a or a == 5 and a > b and b == 1.

  2. comparison-all-equal for a special cycle case where every comparison allows equality. a >= b >= c and c >= a simplifies to a == b == c.

It modifies chained-comparison to be more accurate, specifically the case a < b < c and a < c should be simplified to just a < b < c. It currently is not.

It also prints what simplified comparison is.

Unfortunately, this is at the cost of complexity. The algorithm finds the minimum number of comparisons by finding the longest path through the graph of comparisons repeatedly, recalculating all the path lengths after each path is emitted. (I could not get it working by emitting paths in arbitrary order until all nodes are accounted for because of the case above, a < b < c and a < c.) The overhead of doing so should be limited by the reality that most comparisons tend to have just a few statements.

Please let me know what you think. I'm open to big suggestions, but want to share my code for feedback and to keep this moving.

Type of Changes

Type
✨ New feature

Description

Closes #5814

@coveralls

coveralls commented Oct 12, 2022

Copy link
Copy Markdown

Pull Request Test Coverage Report for Build 3231501930

  • 143 of 143 (100.0%) changed or added relevant lines in 2 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.03%) to 95.357%

Totals Coverage Status
Change from base Build 3225859940: 0.03%
Covered Lines: 17231
Relevant Lines: 18070

💛 - Coveralls

@github-actions

This comment has been minimized.

@Pierre-Sassoulas Pierre-Sassoulas added Enhancement ✨ Improvement to a component Needs review 🔍 Needs to be reviewed by one or multiple more persons labels Oct 12, 2022

@Pierre-Sassoulas Pierre-Sassoulas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the work @areveny. There's a lot to review but from what I can see after a surface review it's possible that making the gragh check's code independent from the RefactoringChecker might be a good idea, because 1) There's a lot of code and maintenance would benefit from it being separated 2) It's going to be easier if we want to extends usiing-constant-testsdirectly where it's at instead of refactoring how the checker work to be able to raise any message anywhere.

Comment thread pylint/checkers/refactoring/refactoring_checker.py Outdated
"Emitted when items in a boolean condition are all <= or >="
"This is equivalent to asking if they all equal.",
),
"R1738": (

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this should raise the existing message for constant comparison using-constant-test (https://pylint.pycqa.org/en/latest/user_guide/messages/warning/using-constant-test.html#using-constant-test-w0125). We might need to relax some constraint on what checker can do, I'm not sure a checker can raise messages it does not define right now.

@jacobtylerwalls

Copy link
Copy Markdown
Member

Hi @areveny, just wondering: are the false negatives in the primer result one of the items you were hoping to polish after getting an initial review?

@Pierre-Sassoulas Pierre-Sassoulas added the Needs take over 🛎️ Orignal implementer went away but the code could be salvaged. label Jan 16, 2023
Comment thread pylint/graph.py Outdated
Comment thread pylint/checkers/refactoring/refactoring_checker.py Outdated
Comment thread pylint/checkers/refactoring/refactoring_checker.py Outdated
Comment thread pylint/checkers/refactoring/refactoring_checker.py Outdated
@codecov

codecov Bot commented Jan 16, 2023

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.26%. Comparing base (3d7ac12) to head (eea2c46).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #7611      +/-   ##
==========================================
+ Coverage   96.22%   96.26%   +0.03%     
==========================================
  Files         178      178              
  Lines       19699    19857     +158     
==========================================
+ Hits        18956    19115     +159     
+ Misses        743      742       -1     
Files with missing lines Coverage Δ
pylint/checkers/refactoring/refactoring_checker.py 98.47% <100.00%> (+0.15%) ⬆️
pylint/graph.py 91.41% <100.00%> (+5.29%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Pierre-Sassoulas Pierre-Sassoulas added this to the 4.1.0 milestone May 18, 2026
@Pierre-Sassoulas Pierre-Sassoulas removed the Needs take over 🛎️ Orignal implementer went away but the code could be salvaged. label May 18, 2026
@Pierre-Sassoulas Pierre-Sassoulas self-assigned this May 18, 2026
- Rename comparison-all-equal symbol to chained-comparison-all-equal.
- Renumber the two new messages to R1738/R1739 (R1737 is now use-yield-from).
- Drop the leftover comparison-all-equal emit and emit the renamed symbol.
- Fix the evalutes typo in the impossible-comparison message.
- Include the simplified equality form in the chained-comparison-all-equal
  message and rephrase descriptions.
- Tighten the type hints on the new helpers and on
  _get_compare_operand_value (it can be a static method).
- Make the graph helpers added for this check private and modernize their
  signatures.
- Register the new symbols on visit_boolop's
  only_required_for_messages decorator.
- Add documentation pages, bad.py / good.py examples and news
  fragments for the new checks.
Consolidate the two new_check fragments under pylint-dev#5814 into a single file
(the script/check_newsfragments.py validator requires the filename stem to
match the referenced issue) and reference the PR for the false_negative
fragment instead.

Apply pydocstringformatter and black tweaks on graph.py / refactoring_checker.py.
@github-actions

This comment has been minimized.

Before this change, _check_comparisons bailed out as soon as it saw a
statement that wasn't a simple Compare (e.g. a function call or a Compare
with an unsupported operator like !=). That meant common patterns
like _is_int(v) and v >= 0 and v <= 999 never produced a suggestion.

The check now skips those statements but keeps their source text, so the
suggestion shows the full simplified condition (e.g.
_is_int(v) and 999 >= v >= 0) instead of being silent. Partial Compare
statements no longer leak half-committed edges into the graph either —
edges for a Compare are only mutated once the whole statement has been
verified to be processable.
``a > 1 and a < 10`` now suggests ``1 < a < 10`` instead of
``10 > a > 1``. The graph is still normalised largest-first internally
(it makes the cycle and ordering math simpler), but ``_render_path`` now
walks it in reverse and flips the operators when emitting the user-facing
text, so the suggestion reads in the direction Python code idiomatically
writes a range check (``0 <= v <= 999``).

Equality-only paths keep their original direction so ``b == 2`` is not
rewritten as ``2 == b``.
The four parallel dicts (edges / symbols / indegree / frequency) plus the
``unprocessed`` list were being passed around through return tuples and
verbose function signatures. The return type of
``_get_graph_from_comparison_nodes`` in particular spanned eight lines and
was unreadable.

Wrap them in a ``_ComparisonGraph`` dataclass and introduce two TypeAlias
shorthands (``_ComparisonOperand``, ``_ComparisonEdge``) so the helper
signatures shrink to one line. Pull the constant-linking loop out into its
own ``_link_constants`` helper, and rewrite ``_handle_cycles`` to build the
edge list explicitly instead of doing two passes over the cycle. No
behaviour change.
@github-actions

This comment has been minimized.

The check is purely syntactic — ``_get_compare_operand_value`` only
pattern-matches ``nodes.Name`` and ``nodes.Const`` and no ``safe_infer``
call is made — so ``HIGH`` is the right confidence level (same as
``use-yield-from``, ``consider-using-in`` etc.) rather than the implicit
``UNDEFINED`` we had before. Updated the functional test expectations.
Replace the placeholder ``int(input())`` examples with little
function-argument scenarios that show why the pattern matters:

- impossible-comparison uses a botched triangle-inequality check
  (a > b and b > a) and contrasts it with the real inequality.
- chained-comparison-all-equal uses three bodies in thermal
  equilibrium (a >= b and b >= c and c >= a) and simplifies it to
  a == b == c.
@github-actions

This comment has been minimized.

…parts

Before, ``_is_int(v) and v >= 0 and v <= 999`` was being rendered as
``0 <= v <= 999 and _is_int(v)`` because the rendered parts were
alphabetically sorted before being joined. That reordering is unsafe:
``_is_int(v)`` is a type guard whose role is to short-circuit before any
numeric comparison runs, and pulling it after the chain could let a
non-comparable ``v`` raise ``TypeError``.

Split ``node.values`` into runs of consecutive processable Compares
separated by unprocessable boundaries. Each run gets its own graph and can
chain internally; the boundary statements keep their original source-order
slots. The previous all-equal segment shortcut becomes a check across all
graphs, and cycle detection now runs per-segment (a cycle that only exists
across an unprocessable boundary is no longer impossible, since the
boundary can short-circuit).

Also reword the ``_ComparisonGraph`` docstring to drop the codespell-flagged
words (``Multigraph``, ``normalisation``, ``indegree``, ``Consts``) and the
em dashes.
Add a ``test_cycles_do_not_cross_unprocessable_boundaries`` function that
nails down two facts:

- ``a > b and b > a and is_int(v)`` (and the all-equal flavor) still fires
  because the cycle lives entirely within a single run of consecutive
  comparisons.
- ``a > b and is_int(v) and b > a`` does *not* fire even though the cycle
  is a contradiction in isolation. The guard between the two halves can
  short-circuit, so reporting the cycle would be a false positive in the
  general case.
``value == 1 and value == 2`` was firing the new chained-comparison
suggestion as ``value == 2``, but that's wrong: dropping ``value == 1`` is
not safe when the kept constraint doesn't imply it. The pre-PR check
silently ignored all-``==`` conjunctions, keep it that way.

The bug came from ``_link_constants`` adding a synthetic ``>`` edge between
the two constants, which let path-finding produce a misleading chain. The
all-``==`` bailout has to run *before* the synthetic linking. Restructure
``_segment_comparisons`` to stage the per-segment graphs in a ``pending``
list, check all-``==`` across them, then link only if we're going to keep
going. This restores the silence the ``tests/functional/c/consider/consider_using_in.py`` test was relying on.

Also reword the docstring to drop the codespell-flagged ``Unprocessable``.
@github-actions

This comment has been minimized.

- Float Const operand: ``0.5 < a and a < 1.5`` exercises the
  ``isinstance(node.value, (int, float))`` branch of
  ``_get_compare_operand_value`` with a float.
- Attribute/subscript as a Compare operand: ``items[0] < 5 and v > 1
  and v < 10`` trips the ``_get_compare_operand_value`` ``return None``
  branch via an operand (distinct from the existing ``is_int(v)`` test,
  where the whole statement isn't a Compare).
- All-``==`` bailout in ``_segment_comparisons``: the cases ``a == 1
  and a == 2`` and ``a == b and b == c`` lock in the silence restored
  by ddbe375; it was only covered indirectly via ``consider_using_in.py``.
- Mixed-symbol cycle in ``_handle_cycles``: ``a > b and b == a`` and
  ``a >= b and b > a`` cover cycles that pair an inequality with
  ``==`` (existing tests only mixed ``>`` with ``>=``).
@github-actions

This comment has been minimized.

- Drop the ``if not operators: return False`` guard at the end of
  ``_add_compare_to_graph``: ``Compare`` AST nodes always have at least
  one operator, and the per-op loop has already returned ``False`` for
  every unprocessable case, so this branch was unreachable.
- Add ``a < 5 and a > 5`` to ``test_impossible_comparison`` so the
  ``smaller >= largest`` continue in ``_link_constants`` (duplicate
  constants on both sides of a Compare) is exercised.
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Effect of this PR on checked open source code: 🤖

Effect on astropy:

The following messages are now emitted:

Details
  1. locally-disabled:
    Locally disabling chained-comparison-all-equal (R1738)
    https://github.com/astropy/astropy/blob/1fb40bc1f22f176254ef583065aa155f53f3b414/astropy/units/format/cds_parsetab.py#L14
  2. locally-disabled:
    Locally disabling impossible-comparison (R1739)
    https://github.com/astropy/astropy/blob/1fb40bc1f22f176254ef583065aa155f53f3b414/astropy/units/format/cds_parsetab.py#L14
  3. useless-suppression:
    Useless suppression of 'chained-comparison-all-equal'
    https://github.com/astropy/astropy/blob/1fb40bc1f22f176254ef583065aa155f53f3b414/astropy/units/format/cds_parsetab.py#L14
  4. useless-suppression:
    Useless suppression of 'impossible-comparison'
    https://github.com/astropy/astropy/blob/1fb40bc1f22f176254ef583065aa155f53f3b414/astropy/units/format/cds_parsetab.py#L14
  5. locally-disabled:
    Locally disabling chained-comparison-all-equal (R1738)
    https://github.com/astropy/astropy/blob/1fb40bc1f22f176254ef583065aa155f53f3b414/astropy/units/format/generic_parsetab.py#L14
  6. locally-disabled:
    Locally disabling impossible-comparison (R1739)
    https://github.com/astropy/astropy/blob/1fb40bc1f22f176254ef583065aa155f53f3b414/astropy/units/format/generic_parsetab.py#L14
  7. useless-suppression:
    Useless suppression of 'chained-comparison-all-equal'
    https://github.com/astropy/astropy/blob/1fb40bc1f22f176254ef583065aa155f53f3b414/astropy/units/format/generic_parsetab.py#L14
  8. useless-suppression:
    Useless suppression of 'impossible-comparison'
    https://github.com/astropy/astropy/blob/1fb40bc1f22f176254ef583065aa155f53f3b414/astropy/units/format/generic_parsetab.py#L14
  9. locally-disabled:
    Locally disabling chained-comparison-all-equal (R1738)
    https://github.com/astropy/astropy/blob/1fb40bc1f22f176254ef583065aa155f53f3b414/astropy/units/format/ogip_parsetab.py#L14
  10. locally-disabled:
    Locally disabling impossible-comparison (R1739)
    https://github.com/astropy/astropy/blob/1fb40bc1f22f176254ef583065aa155f53f3b414/astropy/units/format/ogip_parsetab.py#L14
  11. useless-suppression:
    Useless suppression of 'chained-comparison-all-equal'
    https://github.com/astropy/astropy/blob/1fb40bc1f22f176254ef583065aa155f53f3b414/astropy/units/format/ogip_parsetab.py#L14
  12. useless-suppression:
    Useless suppression of 'impossible-comparison'
    https://github.com/astropy/astropy/blob/1fb40bc1f22f176254ef583065aa155f53f3b414/astropy/units/format/ogip_parsetab.py#L14
  13. locally-disabled:
    Locally disabling chained-comparison-all-equal (R1738)
    https://github.com/astropy/astropy/blob/1fb40bc1f22f176254ef583065aa155f53f3b414/astropy/coordinates/angles/angle_parsetab.py#L14
  14. locally-disabled:
    Locally disabling impossible-comparison (R1739)
    https://github.com/astropy/astropy/blob/1fb40bc1f22f176254ef583065aa155f53f3b414/astropy/coordinates/angles/angle_parsetab.py#L14
  15. useless-suppression:
    Useless suppression of 'chained-comparison-all-equal'
    https://github.com/astropy/astropy/blob/1fb40bc1f22f176254ef583065aa155f53f3b414/astropy/coordinates/angles/angle_parsetab.py#L14
  16. useless-suppression:
    Useless suppression of 'impossible-comparison'
    https://github.com/astropy/astropy/blob/1fb40bc1f22f176254ef583065aa155f53f3b414/astropy/coordinates/angles/angle_parsetab.py#L14
  17. chained-comparison:
    Simplify chained comparison between the operands: _is_int(v) and 0 <= v <= 999
    https://github.com/astropy/astropy/blob/1fb40bc1f22f176254ef583065aa155f53f3b414/astropy/io/fits/hdu/table.py#L540

The following messages are no longer emitted:

Details
  1. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/astropy/astropy/blob/1fb40bc1f22f176254ef583065aa155f53f3b414/astropy/io/fits/hdu/table.py#L540

Effect on music21:

The following messages are now emitted:

Details
  1. chained-comparison:
    Simplify chained comparison between the operands: startValue < 0 <= minV
    https://github.com/cuthbertLab/music21/blob/65fe74f6584bdeed8421dc57b0452b4d364e4159/music21/graph/axis.py#L273
  2. chained-comparison:
    Simplify chained comparison between the operands: endTimeDifference <= 0 == offsetDifference
    https://github.com/cuthbertLab/music21/blob/65fe74f6584bdeed8421dc57b0452b4d364e4159/music21/tree/verticality.py#L800

The following messages are no longer emitted:

Details
  1. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/cuthbertLab/music21/blob/65fe74f6584bdeed8421dc57b0452b4d364e4159/music21/graph/axis.py#L273

Effect on ansible:

The following messages are now emitted:

Details
  1. chained-comparison:
    Simplify chained comparison between the operands: max_system_uid < current_uid < 500
    https://github.com/ansible/ansible/blob/3f10c2c0a910b15675534891ca567dcde355ad8e/lib/ansible/modules/user.py#L2510
  2. chained-comparison:
    Simplify chained comparison between the operands: highest < gid < 500
    https://github.com/ansible/ansible/blob/3f10c2c0a910b15675534891ca567dcde355ad8e/lib/ansible/modules/group.py#L509

The following messages are no longer emitted:

Details
  1. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/ansible/ansible/blob/3f10c2c0a910b15675534891ca567dcde355ad8e/lib/ansible/modules/user.py#L2510
  2. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/ansible/ansible/blob/3f10c2c0a910b15675534891ca567dcde355ad8e/lib/ansible/modules/group.py#L509

Effect on django:

The following messages are now emitted:

Details
  1. chained-comparison:
    Simplify chained comparison between the operands: start < pos < end
    https://github.com/django/django/blob/ad5ea292748246b2f07f3e379a250985c1ebcba5/django/contrib/staticfiles/storage.py#L222

The following messages are no longer emitted:

Details
  1. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/django/django/blob/ad5ea292748246b2f07f3e379a250985c1ebcba5/django/contrib/staticfiles/storage.py#L222

Effect on pandas:

The following messages are now emitted:

Details
  1. chained-comparison:
    Simplify chained comparison between the operands: result < 0 == neg_ct
    https://github.com/pandas-dev/pandas/blob/b77f5fc2227d91b09f90bebd905cc6ff3ae3c1f4/pandas/core/_numba/kernels/mean_.py#L143

Effect on sentry:

The following messages are now emitted:

Details
  1. chained-comparison:
    Simplify chained comparison between the operands: 60 <= value < 10080
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/rules/actions/utils.py#L74
  2. chained-comparison:
    Simplify chained comparison between the operands: 0 < project_escalation_rate < group_hourly_event_rate
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/tasks/post_process.py#L1473
  3. chained-comparison:
    Simplify chained comparison between the operands: min_last_seen <= last_seen <= max_last_seen
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/tasks/delete_pending_groups.py#L58
  4. chained-comparison:
    Simplify chained comparison between the operands: fcp_minimum_threshold <= fcp < fcp_maximum_threshold
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/issue_detection/detectors/render_blocking_asset_span_detector.py#L51
  5. chained-comparison:
    Simplify chained comparison between the operands: 0 <= alert_limit <= alert_count
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/incidents/endpoints/organization_alert_rule_index.py#L870
  6. chained-comparison:
    Simplify chained comparison between the operands: INDEXING_THRESHOLD <= total_bundles == indexed_bundles
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/debug_files/artifact_bundles.py#L341
  7. chained-comparison:
    Simplify chained comparison between the operands: 0 <= dashboard_limit <= dashboard_count
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/dashboards/endpoints/organization_dashboards.py#L658
  8. chained-comparison:
    Simplify chained comparison between the operands: 0 < weight < 1
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/utils/math.py#L48
  9. chained-comparison:
    Simplify chained comparison between the operands: logical_part_lo_incl <= logical_partition < logical_part_hi_excl
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/ingest/slicing.py#L34
  10. chained-comparison:
    Simplify chained comparison between the operands: 0 < num_cohorts <= 255
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/workflow_engine/processors/schedule.py#L95
  11. chained-comparison:
    Simplify chained comparison between the operands: 0 < byte < 127
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/models/eventattachment.py#L67
  12. chained-comparison:
    Simplify chained comparison between the operands: 200 <= code < 300
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/runner/formatting.py#L33
  13. chained-comparison:
    Simplify chained comparison between the operands: 400 <= code < 500
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/runner/formatting.py#L35

The following messages are no longer emitted:

Details
  1. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/rules/actions/utils.py#L74
  2. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/tasks/post_process.py#L1473
  3. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/tasks/delete_pending_groups.py#L58
  4. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/spans/buffer.py#L234
  5. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/issues/endpoints/serializers.py#L54
  6. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/issues/endpoints/project_ownership.py#L143
  7. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/issue_detection/detectors/render_blocking_asset_span_detector.py#L51
  8. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/web/frontend/js_sdk_loader.py#L80
  9. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/snuba/spans_rpc.py#L182
  10. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/incidents/endpoints/organization_alert_rule_index.py#L870
  11. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/dashboards/endpoints/organization_dashboards.py#L658
  12. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/statistical_detectors/detector.py#L287
  13. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/utils/math.py#L48
  14. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/ingest/slicing.py#L34
  15. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/workflow_engine/endpoints/utils/ids.py#L27
  16. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/workflow_engine/processors/schedule.py#L95
  17. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/models/eventattachment.py#L67
  18. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/runner/formatting.py#L33
  19. chained-comparison:
    Simplify chained comparison between the operands
    https://github.com/getsentry/sentry/blob/7a701584e61d8a093132eb37c45fd0359c1652ee/src/sentry/runner/formatting.py#L35

This comment was generated for commit eea2c46

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Enhancement ✨ Improvement to a component Needs review 🔍 Needs to be reviewed by one or multiple more persons

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Check for circular comparisons and other comparison improvements

4 participants