- Ruff v0.16.0, bộ linter·formatter Python viết bằng Rust, tăng số quy tắc được bật mặc định từ 59 lên 413, giúp phát hiện rộng hơn các lỗi cú pháp và lỗi runtime xảy ra ngay cả khi không cần cấu hình riêng
- Hỗ trợ định dạng khối mã Python trong Markdown được đánh dấu bằng
python, py, pyi, pycon..., và cũng có thể áp dụng cho notebook Quarto
- Bổ sung
ruff: ignore và ruff: file-ignore để chặn chẩn đoán trên từng dòng mã logic hoặc toàn bộ tệp, đồng thời có thể tự động chèn chú thích bằng --add-ignore
check và format --check hiển thị các thay đổi sửa lỗi dưới dạng diff bên dưới chẩn đoán theo mặc định, và kiểm tra formatter cũng hỗ trợ JSON cùng định dạng đầu ra cho chú thích CI của GitHub·GitLab
- Phần lớn có thể nâng cấp mà không cần thay đổi lớn, nhưng cần kiểm tra ảnh hưởng của việc tăng quy tắc mặc định và thay đổi đầu ra JSON khi một số giá trị có thể trở thành
null đối với cấu hình hiện có và công cụ tự động hóa
Mở rộng lên 413 quy tắc mặc định
- Ruff v0.16.0 là bộ linter·formatter Python tốc độ cao viết bằng Rust, có thể cài qua PyPI hoặc
uv tool install ruff@latest
- Tổng số quy tắc của Ruff đã tăng từ 708 ở thời điểm v0.1.0 lên 968, nhưng số quy tắc bật mặc định vẫn được giữ ở 59 cho tới nay
- v0.16 mở rộng số quy tắc mặc định lên 413, phát hiện các vấn đề nghiêm trọng như lỗi cú pháp và lỗi runtime xảy ra ngay mà không cần cấu hình riêng
- Bao gồm các quy tắc thuộc nhóm
B của flake8-bugbear, UP của pyupgrade, và nhóm RUF riêng của Ruff
- Có thể xem toàn bộ danh sách trong tài liệu Default Rules
- Các dự án đã dùng
select hoặc extend-select cũng có thể tìm thấy những quy tắc hữu ích trước đây chưa biết thông qua bộ quy tắc mặc định mới
- Để quay lại bộ quy tắc mặc định cũ, cấu hình như sau
[lint]
select = ["E4", "E7", "E9", "F"]
- Thay đổi lần này gắn với nhiệm vụ dài hạn là phân loại lại quy tắc, và các công việc liên quan dự kiến vẫn sẽ tiếp tục
Định dạng khối mã Markdown
ruff format sẽ định dạng khối mã Python dạng fenced code block nằm trong tệp Markdown
- Các chuỗi thông tin được hỗ trợ là
python, py, python3, py3, pyi, pycon
pyi được xử lý theo định dạng tệp stub
pycon được xử lý theo định dạng phiên REPL
- Các loại còn lại được định dạng như tệp Python thông thường
- Ngay cả khi tên ngôn ngữ được bao bởi dấu ngoặc nhọn như
{python} thì vẫn được nhận diện, nên cũng có thể dùng cho notebook Quarto
- Nếu dùng phần mở rộng
.qmd thì có thể cần cấu hình ánh xạ extension
- Bên trong khối mã, có thể dùng
fmt: off và fmt: on để chặn định dạng một phần
- Có thể loại trừ toàn bộ vùng tài liệu Markdown bằng chú thích HTML
<!-- fmt: off --> và <!-- fmt: on -->
- Để loại trừ mọi tệp Markdown, chỉ định glob như
*.md trong extend-exclude
- Có thể xem hành vi chi tiết trong tài liệu Markdown code formatting
Chú thích chặn chẩn đoán mới
- Tiếp nối cơ chế chặn theo phạm vi
ruff: disable·ruff: enable của v0.15, v0.16 bổ sung ruff: ignore và ruff: file-ignore
ruff: ignore có thể chặn chẩn đoán trên cùng dòng như noqa, hoặc viết thành chú thích độc lập để áp dụng cho toàn bộ dòng logic kế tiếp
- Trong phần khai báo hàm viết nhiều dòng, từ
def đến dấu hai chấm được xem là một dòng logic
ruff: file-ignore sẽ chặn các chẩn đoán được chỉ định trên toàn bộ tệp, tương tự ruff: noqa
- Mỗi chú thích chặn có thể ghi lý do áp dụng sau mã quy tắc
- Tùy chọn CLI
--add-ignore sẽ tự động thêm các chú thích ruff: ignore cần thiết
- Ở chế độ preview, có thể dùng tên quy tắc như
unused-import thay cho mã như F401
- Toàn bộ đặc tả chú thích được tổng hợp trong tài liệu Ruff linter
Diff sửa lỗi và định dạng đầu ra
check và format trước đây cũng hỗ trợ --diff, nhưng hoạt động tách rời với chẩn đoán thông thường nên không hiển thị cùng chẩn đoán giải thích lý do sửa
- Đầu ra mặc định
full của v0.16 hiển thị các thay đổi do linter·formatter có thể thực hiện dưới dạng diff bên dưới chẩn đoán
format --check cũng có thể dùng toàn bộ các định dạng đầu ra mà linter hỗ trợ
- Có thể tạo JSON để máy đọc
- Có thể xuất định dạng mà GitHub và GitLab hiển thị thành chú thích trong CI
- Có thể xem các định dạng được hỗ trợ trong trợ giúp CLI và tài liệu output format
Tương thích và ổn định hóa
- Số thay đổi phá vỡ tương thích trong v0.16 là ít, nên phần lớn có thể cập nhật mà không cần thay đổi lớn về mã hoặc cấu hình
- Trong đầu ra JSON,
filename, location, end_location, fix.edits[].location, fix.edits[].end_location có thể trở thành null thay vì dùng chuỗi rỗng hoặc dòng 1 cột 1 làm giá trị mặc định
- Hiện tại số chẩn đoán bị ảnh hưởng là rất ít, nhưng trong các quy tắc tương lai điều này có thể trở nên phổ biến hơn
- 12 quy tắc được chuyển từ preview sang trạng thái ổn định
- Tương thích chữ ký hàm Airflow 3
AIR303, thông báo bản quyền CPY001, chuyển đổi float FURB164, min/max đã sắp xếp FURB192
- Nối chuỗi trong collection literal
ISC004, ghi log ngoại lệ ngoài exception handler LOG004, kiểu trả về bool sai PLE0304
- Quá nhiều đối số vị trí
PLR0917, trả về StopIteration PLR1708, vị trí None trong Union RUF036
- Truy cập annotation trong từ điển lớp
RUF063, mục trùng lặp trong __all__ RUF068
- Hành vi đã được ổn định hóa của một số quy tắc hiện có cũng được áp dụng mặc định
BLE001 cũng sẽ được chặn khi ghi log ngoại lệ bằng các phương thức logging ngoài critical, error, exception
FA102 kiểm tra thêm các API tương thích PEP 585 như collections.abc
INT001·INT002·INT003 cũng kiểm tra các cách dùng phổ biến như gán gettext vào builtins._
S310 giảm false positive bằng cách phân giải liên kết literal chuỗi cục bộ
S508·S509 hỗ trợ API được khuyến nghị của PySNMP mới nhất
UP019 nhận diện không chỉ typing.Text mà cả typing_extensions.Text
- Có thể xem toàn bộ thay đổi trong GitHub release
1 bình luận
Ý kiến trên Hacker News
Tôi đã nâng một dự án Python khoảng 3 nghìn dòng từ v0.15.x lên phiên bản mới, không mất nhiều thời gian, và nó còn tìm ra khá nhiều vấn đề mà bản trước bỏ sót nên chất lượng mã cũng tốt hơn
Sửa thủ công theo gợi ý: https://github.com/nickjj/plutus/commit/9af66d31f98bef841588...
Bật lại quy tắc độ dài dòng: https://github.com/nickjj/plutus/commit/21789f89bbcee37913c1...
Bắt buộc tiền tố
_cho biến không dùng: https://github.com/nickjj/plutus/commit/a272c77b932e1c78558a...Ruff tự động sửa: https://github.com/nickjj/plutus/commit/6fe69cf88385ebdf9b8c...
Thật mừng khi sau khi Astral được OpenAI mua lại, Ruff, ty, uv vẫn đang được phát triển rất tích cực
uv và Ruff thì rất tuyệt, và hy vọng một ngày nào đó ty cũng đạt tới mức đó
Thật ngạc nhiên khi mọi người lại hào hứng đến vậy với những công cụ cảnh sát cú pháp tự đặt ra đủ kiểu quy tắc và thậm chí còn không thống nhất được thế nào là mã Python tốt
Chúng gộp dictionary nhiều dòng thành một dòng làm hỏng ý nghĩa của comment, rồi chỉ sửa những thứ vụn vặt như hai dấu cách hay dấu ngoặc kép. Vấn đề thực sự không phải khoảng trắng cuối dòng hay sắp xếp import, mà là những list comprehension dài 10 dòng khó hiểu, và các công cụ này lại không bắt được
Ở công ty tôi đã dùng pylint, flake8, black và Ruff, và mỗi thay đổi lại sinh ra hàng trăm commit; có lẽ dùng năng lượng đó vào việc khác sẽ tốt hơn
Nếu cứ chấp nhận kết quả chạy tự động thì có thể đứng ngoài các cuộc tranh luận về lint, nhưng ở những tổ chức không có các công cụ này thì người ta đã phải bỏ thời gian thật để suy nghĩ và tranh luận về định dạng
Trong làm việc nhóm, thay vì quá khăng khăng với sở thích cá nhân, có lẽ nên lắng nghe người xung quanh và xem lại thứ tự ưu tiên giữa cộng tác và tinh thần thủ công
Việc gộp dòng khi có comment theo dòng có vẻ không phù hợp. Dấu ngoặc kép trong Python chỉ là một lựa chọn phong cách đơn thuần, và nếu bên trong dấu nháy đơn có dấu ngoặc kép thì Ruff cũng sẽ để nguyên
Giá mà Go cũng có một công cụ như Ruff. Nhiều ngôn ngữ có công cụ rất tốt, nhưng hệ sinh thái Go bị phân tán và không có công cụ nào cho cảm giác hoàn thiện như Ruff, Oxc, Biome, Mago
Nó tương đối mới nên ít được biết đến hơn, nhưng là nền tảng của go fix và go vet, và có vẻ nhóm Go đang làm để tác giả module có thể dễ dàng định nghĩa các custom analysis pass tự động chạy khi thực thi go fix
Với struct
analysis.Analyzer, bạn có thể truy cập AST, thông tin kiểu, SSA và kết hợp thông tin giữa các analyzer; chỉ cần biên dịch thành binary rồi truyền cho go fix, phần toolchain sẽ xử lý cả việc cache phức tạp. Vì do chính nhóm Go tạo ra và tích hợp vào toolchain, các công cụ như golangci-lint cũng rất có thể về lâu dài sẽ hợp nhất theo framework nàyBạn cũng có thể bảo AI agent viết Go Analysis analyzer rồi chạy bằng go fix, và trong dự án của tôi nó còn được dùng để tự động ép thực thi nhiều quy tắc một cách quyết định luận thay cho các chỉ dẫn Markdown thiếu chính xác
gofmtcho Python. Ruff không phải formatter mà là linter, nhưng hướng phát triển gần đây của hệ sinh thái Python vẫn rất đáng mừngKhác với Python hay TypeScript, nơi công cụ chính thức không ép một style cụ thể, ở Go khó có được hiệu ứng mạnh như lần đầu dùng Ruff hay Biome
Việc bật 413 quy tắc mặc định là một thay đổi tích cực vì đa số dự án có thể nhận được lint hữu ích mà không cần đụng vào cấu hình
Dạo này có thể giao cho agent sửa toàn bộ cảnh báo lint theo một tiêu chuẩn định sẵn rồi để vài tiếng là xong, nhưng bản thân các chẩn đoán chi tiết mà Ruff cung cấp vẫn rất đáng hoan nghênh
Ruff cũng cần một tính năng giống stateVersion của Nix để quyết định bộ giá trị mặc định sẽ áp dụng. Khi cập nhật Ruff trên nhiều kho lưu trữ, mỗi lần có thêm quy tắc mặc định mới thì phải tắt ngay hoặc sửa vi phạm, nên rất khó dự đoán kết quả
Cũng có thể ghi toàn bộ quy tắc cần bật vào danh sách cho phép, nhưng tốt hơn là giữ cấu hình đơn giản và chỉ nâng phiên bản trạng thái khi mọi người đều có thể dành vài giờ cho việc đó
pyproject.tomlcho từng dự án. Khi từng dự án sẵn sàng thì nâng phiên bản, như vậy không cần điều phối nhiều dự án cùng lúc, và nếu một cái bị chậm lại thì cũng không chặn phần còn lạihttps://github.com/astral-sh/ruff/releases/tag/v0.1.0
Trong thời đại coding agent, linting mạnh quan trọng hơn bao giờ hết, và tôi muốn thấy nhiều công cụ như forbidigo hơn ở các ngôn ngữ khác
Coding agent cũng tiêu tốn rất nhiều token để sửa các vấn đề vụn vặt, hoặc nếu test thất bại thì thậm chí vô hiệu hóa hẳn. Tôi đã bắt đầu tin vào độ chính xác tổng thể của kết quả AI, nhưng khả năng phán đoán về chất lượng mã thì vẫn rất khó tin tưởng
Dù đã có tới 413 quy tắc, mỗi lần tham gia một codebase mới tôi vẫn phải lặp lại y hệt ba cuộc tranh luận về việc sắp xếp import
Giờ có vẻ như cách dùng không cần cấu hình đang được khuyến nghị, điều này thật đáng mừng. Với
.ruff.tomlmới, chỉ cần đểline-length = 300là đủ