Skip to content

Conversation

chirizxc
Copy link
Contributor

@chirizxc chirizxc commented Jul 8, 2025

Summary

Part of #2331

Test Plan

update snapshots for preview mode

@chirizxc chirizxc marked this pull request as draft July 8, 2025 17:54
Copy link

codspeed-hq bot commented Jul 8, 2025

CodSpeed Instrumentation Performance Report

Merging #19213 will not alter performance

Comparing chirizxc:feat/more-autofixes (327cafb) with main (8f400bb)

Summary

✅ 40 untouched benchmarks

@chirizxc
Copy link
Contributor Author

chirizxc commented Jul 8, 2025

@ntBre I was wondering if we need a new test, there are none for PTH100 - PTH200

@chirizxc
Copy link
Contributor Author

chirizxc commented Jul 8, 2025

изображение

I mean as separate files, they are all scattered in full_name.py, import_as.py, import_from_as.py, import_from_from.py, use_pathlib.py

@ntBre ntBre self-requested a review July 8, 2025 18:24
@chirizxc
Copy link
Contributor Author

chirizxc commented Jul 8, 2025

Since we have already done tests in PTH203.py we can add new files like PTH100 with minimal case:

import os.path, pathlib
from os.path import abspath

path_to_file = "../path/to/file"

os.path.abspath("../path/to/file")
os.path.abspath(pathlib.Path("../path/to/file")))

abspath(path=path_to_file)

Copy link
Contributor

@ntBre ntBre left a comment

Choose a reason for hiding this comment

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

Thanks! I gave this a quick skim and it looks reasonable to me. I also had an idea for helping with the benchmark regression.

I don't think we need to move the tests around. It seems okay, if not ideal, that they are scattered in these various files. I think the existing tests, plus the new tests you added in the previous PR, should give us good enough coverage.

I'll take another look at this once CI is passing to make sure all the new snapshots look reasonable.

Comment on lines 35 to 38
if checker
.semantic()
.resolve_qualified_name(&call.func)
.is_none_or(|qualified_name| qualified_name.segments() != ["os", "path", fn_name])
.is_none_or(|qualified_name| qualified_name.segments() != full_import)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we may want to pass the QualifiedName or even the segments into each of these rule functions after computing it in expression.rs. Calling resolve_qualified_name repeatedly stood out to me in the benchmark regression.

@chirizxc
Copy link
Contributor Author

chirizxc commented Jul 8, 2025

it seems to work a little differently 😁

@chirizxc chirizxc force-pushed the feat/more-autofixes branch from 2710d87 to c2705b1 Compare July 8, 2025 19:32
@chirizxc chirizxc marked this pull request as ready for review July 8, 2025 19:39
@chirizxc chirizxc marked this pull request as draft July 8, 2025 19:40
@chirizxc
Copy link
Contributor Author

chirizxc commented Jul 8, 2025

it seems we will need to revise all the parameters, I found a bug in the python documentation

@ntBre
Copy link
Contributor

ntBre commented Jul 8, 2025

it seems we will need to revise all the parameters, I found a bug in the python documentation

Wow, nice catch!

Copy link
Contributor

github-actions bot commented Jul 8, 2025

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

ℹ️ ecosystem check detected linter changes. (+0 -0 violations, +2122 -0 fixes in 6 projects; 49 projects unchanged)

apache/airflow (+0 -0 violations, +842 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --no-fix --output-format concise --preview --select ALL

+ airflow-core/docs/conf.py:330:29: PTH100 [*] `os.path.abspath()` should be replaced by `Path.resolve()`
- airflow-core/docs/conf.py:330:29: PTH100 `os.path.abspath()` should be replaced by `Path.resolve()`
+ airflow-core/src/airflow/cli/cli_config.py:109:16: PTH112 [*] `os.path.isdir()` should be replaced by `Path.is_dir()`
- airflow-core/src/airflow/cli/cli_config.py:109:16: PTH112 `os.path.isdir()` should be replaced by `Path.is_dir()`
+ airflow-core/src/airflow/cli/commands/api_server_command.py:158:16: PTH113 [*] `os.path.isfile()` should be replaced by `Path.is_file()`
- airflow-core/src/airflow/cli/commands/api_server_command.py:158:16: PTH113 `os.path.isfile()` should be replaced by `Path.is_file()`
+ airflow-core/src/airflow/cli/commands/api_server_command.py:160:16: PTH113 [*] `os.path.isfile()` should be replaced by `Path.is_file()`
- airflow-core/src/airflow/cli/commands/api_server_command.py:160:16: PTH113 `os.path.isfile()` should be replaced by `Path.is_file()`
+ airflow-core/src/airflow/cli/commands/connection_command.py:324:8: PTH110 [*] `os.path.exists()` should be replaced by `Path.exists()`
- airflow-core/src/airflow/cli/commands/connection_command.py:324:8: PTH110 `os.path.exists()` should be replaced by `Path.exists()`
+ airflow-core/src/airflow/cli/commands/info_command.py:302:31: PTH110 [*] `os.path.exists()` should be replaced by `Path.exists()`
- airflow-core/src/airflow/cli/commands/info_command.py:302:31: PTH110 `os.path.exists()` should be replaced by `Path.exists()`
+ airflow-core/src/airflow/cli/commands/info_command.py:73:21: PTH111 [*] `os.path.expanduser()` should be replaced by `Path.expanduser()`
- airflow-core/src/airflow/cli/commands/info_command.py:73:21: PTH111 `os.path.expanduser()` should be replaced by `Path.expanduser()`
+ airflow-core/src/airflow/cli/commands/pool_command.py:98:12: PTH110 [*] `os.path.exists()` should be replaced by `Path.exists()`
- airflow-core/src/airflow/cli/commands/pool_command.py:98:12: PTH110 `os.path.exists()` should be replaced by `Path.exists()`
... 195 additional changes omitted for rule PTH110
+ airflow-core/src/airflow/config_templates/airflow_local_settings.py:54:24: PTH111 [*] `os.path.expanduser()` should be replaced by `Path.expanduser()`
- airflow-core/src/airflow/config_templates/airflow_local_settings.py:54:24: PTH111 `os.path.expanduser()` should be replaced by `Path.expanduser()`
+ airflow-core/src/airflow/config_templates/default_webserver_config.py:32:11: PTH100 [*] `os.path.abspath()` should be replaced by `Path.resolve()`
... 823 additional changes omitted for project

apache/superset (+0 -0 violations, +46 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --no-fix --output-format concise --preview --select ALL

+ docker/pythonpath_dev/superset_config.py:117:16: PTH120 [*] `os.path.dirname()` should be replaced by `Path.parent`
- docker/pythonpath_dev/superset_config.py:117:16: PTH120 `os.path.dirname()` should be replaced by `Path.parent`
+ docker/pythonpath_dev/superset_config.py:118:21: PTH100 [*] `os.path.abspath()` should be replaced by `Path.resolve()`
- docker/pythonpath_dev/superset_config.py:118:21: PTH100 `os.path.abspath()` should be replaced by `Path.resolve()`
+ scripts/cypress_run.py:135:18: PTH120 [*] `os.path.dirname()` should be replaced by `Path.parent`
- scripts/cypress_run.py:135:18: PTH120 `os.path.dirname()` should be replaced by `Path.parent`
+ scripts/cypress_run.py:135:34: PTH100 [*] `os.path.abspath()` should be replaced by `Path.resolve()`
- scripts/cypress_run.py:135:34: PTH100 `os.path.abspath()` should be replaced by `Path.resolve()`
+ scripts/erd/erd.py:173:22: PTH120 [*] `os.path.dirname()` should be replaced by `Path.parent`
- scripts/erd/erd.py:173:22: PTH120 `os.path.dirname()` should be replaced by `Path.parent`
... 15 additional changes omitted for rule PTH120
... 36 additional changes omitted for project

bokeh/bokeh (+0 -0 violations, +298 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --no-fix --output-format concise --preview --select ALL

+ examples/server/app/export_csv/main.py:15:23: PTH120 [*] `os.path.dirname()` should be replaced by `Path.parent`
- examples/server/app/export_csv/main.py:15:23: PTH120 `os.path.dirname()` should be replaced by `Path.parent`
+ examples/server/app/movies/main.py:28:16: PTH120 [*] `os.path.dirname()` should be replaced by `Path.parent`
- examples/server/app/movies/main.py:28:16: PTH120 `os.path.dirname()` should be replaced by `Path.parent`
+ examples/server/app/simple_hdf5/main.py:17:11: PTH120 [*] `os.path.dirname()` should be replaced by `Path.parent`
- examples/server/app/simple_hdf5/main.py:17:11: PTH120 `os.path.dirname()` should be replaced by `Path.parent`
... 81 additional changes omitted for rule PTH120
+ release/checks.py:80:12: PTH110 [*] `os.path.exists()` should be replaced by `Path.exists()`
- release/checks.py:80:12: PTH110 `os.path.exists()` should be replaced by `Path.exists()`
+ scripts/sri.py:30:24: PTH119 [*] `os.path.basename()` should be replaced by `Path.name`
- scripts/sri.py:30:24: PTH119 `os.path.basename()` should be replaced by `Path.name`
... 288 additional changes omitted for project

latchbio/latch (+0 -0 violations, +8 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --no-fix --output-format concise --preview

+ docs/source/conf.py:18:20: PTH100 [*] `os.path.abspath()` should be replaced by `Path.resolve()`
- docs/source/conf.py:18:20: PTH100 `os.path.abspath()` should be replaced by `Path.resolve()`
+ src/latch_cli/centromere/utils.py:133:46: PTH111 [*] `os.path.expanduser()` should be replaced by `Path.expanduser()`
- src/latch_cli/centromere/utils.py:133:46: PTH111 `os.path.expanduser()` should be replaced by `Path.expanduser()`
+ src/latch_cli/snakemake/serialize.py:126:16: PTH117 [*] `os.path.isabs()` should be replaced by `Path.is_absolute()`
- src/latch_cli/snakemake/serialize.py:126:16: PTH117 `os.path.isabs()` should be replaced by `Path.is_absolute()`
+ src/latch_cli/snakemake/workflow.py:120:33: PTH112 [*] `os.path.isdir()` should be replaced by `Path.is_dir()`
- src/latch_cli/snakemake/workflow.py:120:33: PTH112 `os.path.isdir()` should be replaced by `Path.is_dir()`

milvus-io/pymilvus (+0 -0 violations, +18 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --no-fix --output-format concise --preview

+ docs/source/conf.py:15:20: PTH100 [*] `os.path.abspath()` should be replaced by `Path.resolve()`
- docs/source/conf.py:15:20: PTH100 `os.path.abspath()` should be replaced by `Path.resolve()`
+ examples/bulk_import/example_bulkinsert_csv.py:283:12: PTH110 [*] `os.path.exists()` should be replaced by `Path.exists()`
- examples/bulk_import/example_bulkinsert_csv.py:283:12: PTH110 `os.path.exists()` should be replaced by `Path.exists()`
+ examples/bulk_import/example_bulkinsert_csv.py:305:74: PTH119 [*] `os.path.basename()` should be replaced by `Path.name`
- examples/bulk_import/example_bulkinsert_csv.py:305:74: PTH119 `os.path.basename()` should be replaced by `Path.name`
+ examples/bulk_import/example_bulkinsert_json.py:325:12: PTH110 [*] `os.path.exists()` should be replaced by `Path.exists()`
- examples/bulk_import/example_bulkinsert_json.py:325:12: PTH110 `os.path.exists()` should be replaced by `Path.exists()`
+ examples/bulk_import/example_bulkinsert_json.py:347:74: PTH119 [*] `os.path.basename()` should be replaced by `Path.name`
- examples/bulk_import/example_bulkinsert_json.py:347:74: PTH119 `os.path.basename()` should be replaced by `Path.name`
... 8 additional changes omitted for project

zulip/zulip (+0 -0 violations, +910 -0 fixes)

ruff check --no-cache --exit-zero --ignore RUF9 --no-fix --output-format concise --preview --select ALL

+ corporate/tests/test_stripe.py:202:9: PTH107 [*] `os.remove()` should be replaced by `Path.unlink()`
- corporate/tests/test_stripe.py:202:9: PTH107 `os.remove()` should be replaced by `Path.unlink()`
+ docs/conf.py:11:20: PTH100 [*] `os.path.abspath()` should be replaced by `Path.resolve()`
- docs/conf.py:11:20: PTH100 `os.path.abspath()` should be replaced by `Path.resolve()`
+ docs/conf.py:11:49: PTH120 [*] `os.path.dirname()` should be replaced by `Path.parent`
- docs/conf.py:11:49: PTH120 `os.path.dirname()` should be replaced by `Path.parent`
+ manage.py:7:12: PTH120 [*] `os.path.dirname()` should be replaced by `Path.parent`
- manage.py:7:12: PTH120 `os.path.dirname()` should be replaced by `Path.parent`
+ manage.py:7:28: PTH100 [*] `os.path.abspath()` should be replaced by `Path.resolve()`
- manage.py:7:28: PTH100 `os.path.abspath()` should be replaced by `Path.resolve()`
+ scripts/lib/check_rabbitmq_queue.py:10:14: PTH120 [*] `os.path.dirname()` should be replaced by `Path.parent`
- scripts/lib/check_rabbitmq_queue.py:10:14: PTH120 `os.path.dirname()` should be replaced by `Path.parent`
... 253 additional changes omitted for rule PTH120
+ scripts/lib/check_rabbitmq_queue.py:10:62: PTH100 [*] `os.path.abspath()` should be replaced by `Path.resolve()`
- scripts/lib/check_rabbitmq_queue.py:10:62: PTH100 `os.path.abspath()` should be replaced by `Path.resolve()`
... 89 additional changes omitted for rule PTH100
+ scripts/lib/check_rabbitmq_queue.py:190:16: PTH110 [*] `os.path.exists()` should be replaced by `Path.exists()`
- scripts/lib/check_rabbitmq_queue.py:190:16: PTH110 `os.path.exists()` should be replaced by `Path.exists()`
+ scripts/lib/clean_emoji_cache.py:32:16: PTH114 [*] `os.path.islink()` should be replaced by `Path.is_symlink()`
- scripts/lib/clean_emoji_cache.py:32:16: PTH114 `os.path.islink()` should be replaced by `Path.is_symlink()`
+ scripts/lib/clean_emoji_cache.py:37:43: PTH115 [*] `os.readlink()` should be replaced by `Path.readlink()`
- scripts/lib/clean_emoji_cache.py:37:43: PTH115 `os.readlink()` should be replaced by `Path.readlink()`
+ scripts/lib/node_cache.py:10:9: PTH108 [*] `os.unlink()` should be replaced by `Path.unlink()`
... 889 additional changes omitted for project

Changes by rule (13 rules affected)

code total + violation - violation + fix - fix
PTH120 568 0 0 568 0
PTH110 546 0 0 546 0
PTH100 208 0 0 208 0
PTH119 208 0 0 208 0
PTH113 186 0 0 186 0
PTH107 170 0 0 170 0
PTH112 88 0 0 88 0
PTH111 74 0 0 74 0
PTH108 28 0 0 28 0
PTH114 22 0 0 22 0
PTH117 12 0 0 12 0
PTH115 6 0 0 6 0
PTH106 6 0 0 6 0

@AA-Turner
Copy link
Contributor

it seems we will need to revise all the parameters ...

I would suggest treating the os.path functions as positional only in the general case. Using keyword arguments for them is to be avoided.

@chirizxc chirizxc marked this pull request as ready for review July 8, 2025 20:37
@chirizxc
Copy link
Contributor Author

chirizxc commented Jul 8, 2025

Is such a regression acceptable? there are many autofixes for rules after all

@ntBre ntBre added fixes Related to suggested fixes for violations preview Related to preview mode features labels Jul 8, 2025
Copy link
Contributor

@ntBre ntBre left a comment

Choose a reason for hiding this comment

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

Thanks, this looks good! The one thing we probably should do is add a preview test for these other rules on their existing files. So basically copy this test and enable preview:

#[test_case(Path::new("full_name.py"))]
#[test_case(Path::new("import_as.py"))]
#[test_case(Path::new("import_from_as.py"))]
#[test_case(Path::new("import_from.py"))]
#[test_case(Path::new("use_pathlib.py"))]
fn rules(path: &Path) -> Result<()> {

I think that should cover the preview behavior for all of these.

@chirizxc
Copy link
Contributor Author

chirizxc commented Jul 9, 2025

also, can you please update that table from #2331?

@chirizxc
Copy link
Contributor Author

chirizxc commented Jul 9, 2025

windows runner 🫡

@chirizxc chirizxc changed the title [flake8-use-pathlib] Add autofixes for PTH100, PTH106, PTH107, PTH108, PTH110, PTH111, PTH112, PTH113, PTH114, PTH115, PTH117, PTH118, PTH119 [flake8-use-pathlib] Add autofixes for PTH100, PTH106, PTH107, PTH108, PTH110, PTH111, PTH112, PTH113, PTH114, PTH115, PTH117, PTH118, PTH119, PTH120 Jul 9, 2025
@chirizxc chirizxc changed the title [flake8-use-pathlib] Add autofixes for PTH100, PTH106, PTH107, PTH108, PTH110, PTH111, PTH112, PTH113, PTH114, PTH115, PTH117, PTH118, PTH119, PTH120 [flake8-use-pathlib] Add autofixes for PTH100, PTH106, PTH107, PTH108, PTH110, PTH111, PTH112, PTH113, PTH114, PTH115, PTH117, PTH119, PTH120 Jul 9, 2025
@ntBre ntBre merged commit beb98da into astral-sh:main Jul 9, 2025
57 of 58 checks passed
@chirizxc chirizxc deleted the feat/more-autofixes branch July 9, 2025 19:01
UnboundVariable pushed a commit to UnboundVariable/ruff that referenced this pull request Jul 10, 2025
…re_help

* 'main' of https://github.com/astral-sh/ruff: (34 commits)
  [docs] add capital one to who's using ruff (astral-sh#19248)
  [`pyupgrade`] Keyword arguments in `super` should suppress the `UP008` fix (astral-sh#19131)
  [`flake8-use-pathlib`] Add autofixes for `PTH100`, `PTH106`, `PTH107`, `PTH108`, `PTH110`, `PTH111`, `PTH112`, `PTH113`, `PTH114`, `PTH115`, `PTH117`, `PTH119`, `PTH120` (astral-sh#19213)
  [ty] Do not run `mypy_primer.yaml` when all changed files are Markdown files (astral-sh#19244)
  [`flake8-bandit`] Make example error out-of-the-box (`S412`) (astral-sh#19241)
  [`pydoclint`] Make example error out-of-the-box (`DOC501`) (astral-sh#19218)
  [ty] Add "kind" to completion suggestions
  [ty] Add type information to `all_members` API
  [ty] Expand API of `all_members` to return a struct
  [ty] Ecosystem analyzer PR comment workflow (astral-sh#19237)
  [ty] Merge `ty_macros` into `ruff_macros` (astral-sh#19229)
  [ty] Fix `ClassLiteral.into_callable` for dataclasses (astral-sh#19192)
  [ty] `dataclasses.field` support (astral-sh#19140)
  [ty] Fix panic for attribute expressions with empty value (astral-sh#19069)
  [ty] Return `CallableType` from `BoundMethodType.into_callable_type` (astral-sh#19193)
  [`flake8-bugbear`] Support non-context-manager calls in `B017` (astral-sh#19063)
  [ty] Improved diagnostic for reassignments of `Final` symbols (astral-sh#19214)
  [ty] Use full range for assignment definitions (astral-sh#19211)
  [`pylint`] Update `missing-maxsplit-arg` docs and error to suggest proper usage (`PLC0207`) (astral-sh#18949)
  [ty] Add `set -eu` to mypy-primer script (astral-sh#19212)
  ...

# Conflicts:
#	crates/ty_python_semantic/src/types/class.rs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fixes Related to suggested fixes for violations preview Related to preview mode features
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants