Releases: astral-sh/ruff
v0.0.278
See the release blog post for more, including detailed descriptions of any newly added rules.
What's Changed
Rules
- [
pylint
] Implementtypevar-bivariance
(PLC0131
) by @tjkuson in #5517 - [
flake8-pyi
] Implementunnecessary-literal-union
(PYI030
) by @zanieb in #5570 - [
pylint
] Implementtype-name-incorrect-variance
(PLC0105
) by @tjkuson in #5651 - [
ruff
] Implementunnecessary-list-allocation-for-first-element
(RUF015
) by @evanrittenhouse in #5549 - [
flake8-bugbear
] Implementre-sub-positional-args
(B034
) by @charliermarsh in #5669 - [
ruff
] Implementinvalid-index-type
(RUF016
) by @zanieb in #5602
Settings
- [
isort
] Add--case-sensitive
flag by @qdegraaf in #5539 - [
isort
] Support globbing inisort
options by @tjkuson in #5473
Bug Fixes
- Support autofix for some multiline
str.format
calls by @harupy in #5638 - Avoid triggering
unnecessary-map
(C417
) for late-bound lambdas by @charliermarsh in #5520 - Avoid triggering DTZ001-006 when using
.astimezone()
by @dhruvmanila in #5524 - Enable attribute lookups via semantic model by @charliermarsh in #5536
- Avoid syntax errors when rewriting str(dict) in f-strings by @charliermarsh in #5538
- Differentiate between runtime and typing-time annotations by @charliermarsh in #5575
- Only run pyproject.toml lint rules when enabled by @charliermarsh in #5578
- Refactor isort directive skips to use iterators by @charliermarsh in #5623
- Allow descriptor instantiations in dataclass fields by @charliermarsh in #5537
- Refactor
noqa
directive parsing away from regex-based implementation by @charliermarsh in #5554 - Emit warnings for invalid
# noqa
directives by @charliermarsh in #5571 - Support individual codes on
# flake8: noqa
directives by @charliermarsh in #5618 - Add
tkinter
import convention by @tjkuson in #5626 - Avoid
PERF401
if conditional depends on list var by @dhruvmanila in #5603 - Fix typo in complex-if-statement-in-stub message by @charliermarsh in #5635
- Make TRY301 trigger only if a
raise
throws a caught exception by @evanrittenhouse in #5455 - Skip flake8-future-annotations checks in stub files by @charliermarsh in #5652
- Always allow PEP 585 and PEP 604 rewrites in stub files by @charliermarsh in #5653
- Add support for
Union
declarations without|
to PYI016 by @zanieb in #5598 - Ignore
_name_
and_value_
accesses inflake8-self
rules by @monosans in #5663 - Refactor
repeated_keys()
to useComparableExpr
by @qdegraaf in #5696
New Contributors
- @karosis88 made their first contribution in #5560
- @petermattia made their first contribution in #5579
- @DimitriPapadopoulos made their first contribution in #5607
Full Changelog: v0.0.277...v0.0.278
v0.0.277
What's Changed
Breaking Changes
- Add .ipynb_checkpoints, .pyenv, .pytest_cache, and .vscode to default excludes by @charliermarsh in #5513
Rules
Settings
Bug Fixes
- Fix eval detection for suspicious-eval-usage by @charliermarsh in #5506
- Avoid PERF rules for iteration-dependent assignments by @charliermarsh in #5508
- Avoid returning first-match for rule prefixes by @charliermarsh in #5511
Full Changelog: v0.0.276...v0.0.277
v0.0.276
See the release blog post for more, including detailed descriptions of any newly added rules.
What's Changed
Highlights include: experimental support for linting Jupyter Notebooks.
To opt-in to linting Jupyter Notebook files, add the *.ipynb
pattern to your include
setting, like so:
[tool.ruff]
# Allow Ruff to discover `*.ipynb` files.
include = ["*.py", "*.pyi", "**/pyproject.toml", "*.ipynb"]
This will prompt Ruff to discover Jupyter Notebook files in any specified directories, and lint them
accordingly.
Jupyter Notebook support is currently opt-in and experimental. We'd love your help testing it out.
Have feedback? Run into issues? Let us know!
New Rules
- [
flake8-pyi
] ImplementPYI002
,PYI003
,PYI004
,PYI005
by @density in #5457 - [
numpy
] Implementnumpy-deprecated-function
(NPY003
) by @charliermarsh in #5468 - [
perflint
] Implementunnecessary-list-cast
(PERF101
) by @qdegraaf in #5121 - [
perflint
] Implementtry-except-in-loop
(PERF203
) by @evanrittenhouse in #5166 - [
perflint
] Implementmanual-list-comprehension
(PERF401
) andmanual-list-copy
(PERF402
) rules by @qdegraaf in #5298 - [
pylint
] Implement Pylintsingle-string-used-for-slots
(C0205
) assingle-string-slots
(PLC0205
) by @tjkuson in #5399
Jupyter
- Experimental release for Jupyter notebook integration by @dhruvmanila in #5363
- Enable --watch for Jupyter notebooks by @charliermarsh in #5394
- Consider Jupyter index for code frames (
--show-source
) by @dhruvmanila in #5402 - fixup! Consider Jupyter index for code frames (
--show-source
) (#5402) by @dhruvmanila in #5414
Settings
- [
pyupgrade
] Restore thekeep-runtime-typing
setting by @charliermarsh in #5470 - Add
PythonVersion::Py312
by @charliermarsh in #5316
Bug Fixes
- Support
pydantic.BaseSettings
inmutable-class-default
by @charliermarsh in #5312 - Allow
__slots__
assignments inmutable-class-default
by @charliermarsh in #5314 - Avoid syntax errors when removing f-string prefixes by @charliermarsh in #5319
- Ignore unpacking in
iteration-over-set
by @charliermarsh in #5392 - Replace same length equal line with dash line in D407 by @dhruvmanila in #5383
- Exclude docstrings from PYI053 by @intgr in #5405
- Use "manual" fixability for E731 in shadowed context by @charliermarsh in #5430
- Detect consecutive, non-newline-delimited NumPy sections by @charliermarsh in #5467
- Fix
unnecessary-encode-utf8
to fixencode
on parenthesized strings correctly by @harupy in #5478 - Allow
Final
assignments in stubs by @charliermarsh in #5490 - Respect
abc
decorators when classifying function types by @charliermarsh in #5315 - Allow
@Author
format for "Missing Author" rule inflake8-todos
by @mayrholu in #4903 - Ignore type aliases for RUF013 by @dhruvmanila in #5344
- Change W605 autofix to use raw strings if possible by @hauntsaninja in #5352
- Add space when migrating to raw string by @charliermarsh in #5358
- Update the
invalid-escape-sequence
rule by @charliermarsh in #5359 - Include BaseException in B017 rule by @charliermarsh in #5466
- [
flake8-django
] Skip duplicate violations inDJ012
by @charliermarsh in #5469
New Contributors
- @mayrholu made their first contribution in #4903
- @hauntsaninja made their first contribution in #5352
- @ethunk made their first contribution in #5397
- @LouisDISPA made their first contribution in #5475
Full Changelog: v0.0.275...v0.0.276
v0.0.275
What's Changed
Highlights include a 7-10x decrease in Ruff's cache size.
Rules
- Add support for top-level quoted annotations in RUF013 by @charliermarsh in #5235
- Add support for nested quoted annotations in RUF013 by @dhruvmanila in #5254
- Move
compare-to-empty-string
(PLC1901
) to nursery by @charliermarsh in #5264 - Ignore Pydantic classes when evaluating
mutable-class-default
(RUF012
) by @charliermarsh in #5273 - Allow
typing.Final
formutable-class-default annotations
(RUF012
) by @charliermarsh in #5274 - Modify
deprecated-import
(UP035
) to prefertyping_extensions
in some versions by @tjkuson in #5291
Bug Fixes
- Restore existing bindings when unbinding caught exceptions by @charliermarsh in #5256
- Avoid including nursery rules in linter-level selectors by @charliermarsh in #5268
New Contributors
Full Changelog: v0.0.274...v0.0.275
v0.0.274
What's Changed
Follow-up release to v0.0.273
to fix a panic in cache accesses.
Bug Fixes
- Use package roots rather than package members for cache initialization by @charliermarsh in #5233
- Avoid
.unwrap()
on cache access by @charliermarsh in #5229 - Revert change to
RUF010
to remove unnecessarystr
calls by @charliermarsh in #5232 - Avoid erroneous RUF013 violations for quoted annotations by @charliermarsh in #5234
Full Changelog: v0.0.273...v0.0.274
v0.0.273
What's Changed
Highlights include:
- Autofix capabilities for rules like
flake8-import-conventions
, which require symbol renames across a file. - Significant decrease in Ruff's cache size (e.g., a ~50% decrease for FastAPI).
- Dozens and dozens of bug fixes + performance improvements.
Rules
- [
copyright
] Implement copyright notice detection by @Ryang20718 in #4701 - [
flake8-datetimez
] Enable UTC-import fordatetime-utc-alias
fix by @charliermarsh in #5100 - [
flake8-implicit-str-concat
] Add autofix forISC001
by @tkukushkin in #4853 - [
flake8-import-conventions
] Enable autofix for unconventional imports rule by @charliermarsh in #5152 - [
flake8-pyi
] Add autofix forSet
-to-AbstractSet
rewrite using reference tracking by @charliermarsh in #5074 - [
flake8-pyi
] Implement PYI044 by @Thomasdezeeuw in #5021 - [
flake8-return
] Extend revisedRET504
implementation towith
statements by @charliermarsh in #4998 - [
flake8-return
] Implement autofix for revisedRET504
rule by @charliermarsh in #4999 - [
flake8-return
] RefactorRET504
to only enforce assignment-then-return pattern by @charliermarsh in #4997 - [
flake8-slots
] Add plugin, addSLOT000
,SLOT001
andSLOT002
by @qdegraaf in #4909 - [
perflint
] Addperflint
plugin, add first rulePERF102
by @qdegraaf in #4821 - [
pylint
] Add Pylint rulecomparison-with-itself
(R0124
) by @tjkuson in #4957 - [
pyupgrade
] Add a rule to remove unnecessary parentheses in class definitions by @charliermarsh in #5032 - [
ruff
] Add a rule for static keys in dict comprehensions by @rodjunger in #4929 - [
ruff
] Add rule to disallow implicit optional with autofix by @dhruvmanila in #4831 - [
ruff
] Expand RUF008 to all classes, but to a new code (RUF012) by @adampauls in #4390 - [
ruff
] Remove unannotated attributes from RUF008 by @charliermarsh in #5049 - [
ruff
] Upgrade explicit-type-conversion rule (RUF010
) to remove unnecessarystr
calls by @charliermarsh in #4971
Settings
- Option (
-o
/--output-file
) to write output to a file by @dhruvmanila in #4950 - Add JSON Lines (NDJSON) message serialization by @akx in #5048
- Add rule documentation URL to JSON output by @charliermarsh in #5187
Caching
- Only use a single cache file per Python package by @Thomasdezeeuw in #5117
- Open cache files in parallel by @Thomasdezeeuw in #5120
Jupyter
- Add support for auto-fix in Jupyter notebooks by @dhruvmanila in #4665
- Add roundtrip support for Jupyter notebook by @dhruvmanila in #5028
Bug Fixes
- Handle decorators in class-parenthesis-modifying rules by @charliermarsh in #5034
- Allow re-assignments to
__all__
by @charliermarsh in #4967 - Handled dict and set inside f-string (#4249) by @DavideCanton in #4563
- Support concatenated string key removals by @charliermarsh in #4976
- Respect 'is not' operators split across newlines by @charliermarsh in #4977
- Parenthesize expressions prior to lexing in F632 by @charliermarsh in #5001
- Ignore pyproject.toml for adding noqa directives by @dhruvmanila in #5013
- Support 'reason' argument to
pytest.fail
by @charliermarsh in #5040 - Allow
async with
inredefined-loop-name
by @charliermarsh in #5125 - Skip
DJ008
enforcement in stub files by @charliermarsh in #5139 - Detect continuations at start-of-file by @charliermarsh in #5173
- Fix allowed-ellipsis detection by @charliermarsh in #5174
- Remove continuations before trailing semicolons by @charliermarsh in #5199
- Support parenthesized expressions when splitting compound assertions by @charliermarsh in #5219
- Use phf for confusables to reduce llvm lines by @konstin in #4926
- Allow private accesses within special dunder methods by @charliermarsh in #4968
- Support concatenated literals in format-literals by @charliermarsh in #4974
- Fix line numbers in source frames by @MichaReiser in #4984
- Suggest combining async with statements by @Thomasdezeeuw in #5022
- Improve
TypedDict
conversion logic for shadowed builtins and dunder methods by @charliermarsh in #5038 - Support glob patterns in pep8_naming ignore-names by @Thomasdezeeuw in #5024
- Respect all
__all__
definitions for docstring visibility by @charliermarsh in #5052 - Don't treat annotations as resolved in forward references by @charliermarsh in #5060
- Consider ignore-names in all pep8 naming rules by @Thomasdezeeuw in #5079
- Ignore
reimplemented-builtin
if usingawait
by @tjkuson in #5101 - Allow space in filename for powershell + windows + python module by @konstin in #5115
- Don't treat straight imports of future as
__future__
imports by @charliermarsh in #5128 - Remove continuations when deleting statements by @charliermarsh in #5198
- Fix corner case involving terminal backslash after fixing
W293
by @evanrittenhouse in #5172 - Fix subprocess.run on Windows Python 3.7 by @konstin in #5220
New Contributors
- @rodjunger made their first contribution in #4929
- @DavideCanton made their first contribution in #4563
- @Thomasdezeeuw made their first contribution in #5021
- @adampauls made their first contribution in #4390
- @tkukushkin made their first contribution in #4853
- @Taybou made their first contribution in #5088
- @davidszotten made their first contribution in #5158
- @dosisod made their first contribution in #5203
Full Changelog: v0.0.272...v0.0.273
v0.0.272
What's Changed
Breaking Changes
- Move flake8-fixme rules to FIX prefix by @charliermarsh in #4917
Rules
Bug Fixes
- Avoid attributing runtime references to module-level imports by @charliermarsh in #4942
- Skip class scopes when resolving nonlocal references by @charliermarsh in #4943
- Apply
dict.get
fix before ternary rewrite by @charliermarsh in #4944 - Handle implicit string concatenations in conversion-flag rewrites by @charliermarsh in #4947
- Make
C413
fix as suggested forreversed
call by @dhruvmanila in #4891 - ignore if using infinite iterators in
B905
by @kyoto7250 in #4914
Full Changelog: v0.0.271...v0.0.272
v0.0.271
What's Changed
Rules
- Add autofix for flake8-type-checking by @charliermarsh in #4742
- [
airflow
] Add AIR001: task variable name should be same as task_id arg by @jlaneve in #4687 - [
flake8-bandit
] Implement S609, linux_commands_wildcard_injection by @scop in #4504 - [
flake8-bugbear
] Move duplicate-value rule to flake8-bugbear by @charliermarsh in #4882 - [
flake8-fixme
] Implementflake8_fixme
and refactorTodoDirective
by @evanrittenhouse in #4681 - [
flake8-future-annotations
] ImplementFA102
by @akx in #4702 - [
flake8-pyi
] Add PYI024 forflake8-pyi
plugin by @qdegraaf in #4756 - [
flake8-pyi
] Add PYI034 forflake8-pyi
plugin by @qdegraaf in #4764 - [
flake8-pyi
] AddPYI032
rule with autofix by @qdegraaf in #4695 - [
flake8-pyi
] Add autofix for PYI010 by @qdegraaf in #4634 - [
flake8-pyi
] Implement PYI029 by @density in #4851 - [
flake8-pyi
] Implement PYI035 by @density in #4820 - [
flake8-pyi
] Implement PYI048 forflake8-pyi
plugin by @qdegraaf in #4645 - [
flake8-pyi
] Implement PYI053 by @density in #4770 - [
flake8-pyi
] Implement PYI054 by @density in #4775 - [
flake8-pyi
] ImplementPYI025
by @qdegraaf in #4791 - [
flake8-pyi
] ImplementPYI045
by @density in #4700 - [
pylint
] Add Pylint ruleC0208
(use-sequence-for-iteration
) asPLC0208
(iteration-over-set
) by @tjkuson in #4706 - [
pylint
] Add autofix forPLR1701
(repeated-isinstance-calls) by @dhruvmanila in #4792 - [
pylint
] Implement Pylint'syield-inside-async-function
rule (PLE1700
) by @chanman3388 in #4668 - [
pylint
] implement E307 for pylint invalid str return type by @Ryang20718 in #4854 - [
ruff
] Lint pyproject.toml by @konstin in #4496 - [
tryceratops
] Ignore error calls withexc_info
in TRY400 by @charliermarsh in #4797
Settings
- Add
pyflakes.extend-generics
setting by @JonathanPlasse in #4677
Bug Fixes
- Fix PLW3301 false positive single argument nested min/max by @JonathanPlasse in #4683
- Handle dotted alias imports to check for implicit imports by @dhruvmanila in #4685
- Flag empty strings in flake8-errmsg rules by @charliermarsh in #4745
- Exclude function definition from too-many-statements rule by @charliermarsh in #4794
- Preserve quotes in F523 fixer by @charliermarsh in #4836
- Fix round-tripping of nested functions by @charliermarsh in #4875
- Avoid early-exit in explicit-f-string-type-conversion by @charliermarsh in #4886
- Avoid no-op fix for nested with expressions by @charliermarsh in #4906
- Fix UP036 auto-fix error by @JonathanPlasse in #4679
- Use class name as range for
B024
by @charliermarsh in #4647 - Change TODO directive detection to work with multiple pound signs on the same line by @evanrittenhouse in #4558
- Allow more immutable funcs for RUF009 by @qdegraaf in #4660
- Avoid using typing-imported symbols for runtime edits by @charliermarsh in #4649
- Fix
async for
formatting by @charliermarsh in #4675 - Ignore setattr in FBT003 by @alexfikl in #4752
- Include ImportError in non-fixable try-catch imports by @charliermarsh in #4793
- Avoid extra newline between diagnostics in grouped mode by @charliermarsh in #4776
- Avoid enforcing native-literals rule within nested f-strings by @charliermarsh in #4488
- Respect mixed variable assignment in RET504 by @charliermarsh in #4835
- Make FLY002 autofix into a constant string instead of an f-string if all
join()
arguments are strings by @evanrittenhouse in #4834 - Add some exceptions for FBT003 (#3247) by @allisonkarlitskaya in #4867
- Avoid running RUF100 rules when code contains syntax errors by @charliermarsh in #4869
- Avoid index-out-of-bands panic for positional placeholders by @charliermarsh in #4872
- Remove destructive fixes for F523 by @charliermarsh in #4883
- Respect shadowed exports in
__all__
by @charliermarsh in #4885 - Track symbol deletions separately from bindings by @charliermarsh in #4888
- Change fixable_set to include RuleSelector::All/Nursery by @evanrittenhouse in #4852
New Contributors
- @bersbersbers made their first contribution in #4644
- @jlaneve made their first contribution in #4690
- @suharnikov made their first contribution in #4678
- @alexfikl made their first contribution in #4752
- @allisonkarlitskaya made their first contribution in #4867
- @Ryang20718 made their first contribution in #4854
- @addisoncrump made their first contribution in #4893
Full Changelog: v0.0.270...v0.0.271
v0.0.270
What's Changed
Rules
- [
flake8-bandit
] Implementparamiko-call
(S601
) by @scop in #4500 - [
flake8-pyi
] Add autofix for PYI009 by @qdegraaf in #4583 - [
flake8-pyi
] ImplementPYI013
by @density in #4517 - [
pylint
] Addduplicate-value
(W0130
) by @hoel-bagard in #4515 - [
pylint
] Addnamed_expr_without_context
(W0131
) by @hoel-bagard in #4531 - [
ruff
] ExtendRUF005
to recursive and literal-literal concatenations by @hoel-bagard in #4557 - [
ruff
] Make ambiguous-unicode detection sensitive to 'word' context by @charliermarsh in #4552 - [
ruff
] Name ambiguous characters by @covracer in #4448
Settings
- Implement
--extend-fixable
option by @charliermarsh in #4297 - Support new
extend-per-file-ignores
setting by @aacunningham in #4265
Bug Fixes
- Fix RUF010 auto-fix with parenthesis by @JonathanPlasse in #4524
- Parenthesize more sub-expressions in f-string conversion by @charliermarsh in #4535
- Fix false-positive for TRY302 if exception cause is given by @153957 in #4559
- Fix
# isort: split
comment detection in nested blocks by @charliermarsh in #4584 - Avoid some false positives in dunder variable assigments by @scop in #4508
- Fix UP032 auto-fix with integers by @JonathanPlasse in #4525
- Improve reference resolution for deferred-annotations-within-classes by @charliermarsh in #4509
- Improve handling of
__qualname__
,__module__
, and__class__
by @charliermarsh in #4512 - Include empty success test in JUnit output by @charliermarsh in #4537
- Fix SIM110 and SIM111 ranges by @JonathanPlasse in #4545
- Ignore
#region
code folding marks in eradicate rules by @charliermarsh in #4546 - Avoid infinite loop for required imports with isort: off by @charliermarsh in #4581
- Make B007 fix relevance stricter by @charliermarsh in #4607
- Introduce
tab-size
to correcly calculate the line length with tabulations by @JonathanPlasse in #4167 - Visit
TypeVar
andNewType
name arguments by @charliermarsh in #4627 - Improve
Message
sorting performance by @MichaReiser in #4624
New Contributors
- @hoel-bagard made their first contribution in #4516
- @density made their first contribution in #4517
- @Mr-Pepe made their first contribution in #4540
- @153957 made their first contribution in #4559
- @covracer made their first contribution in #4448
Full Changelog: v0.0.269...v0.0.270
v0.0.269
What's Changed
(This is a rerelease of v0.0.268
, which didn't make it to PyPI due to user error. As such, the release notes are copied below.)
pycodestyle
This release includes optimized implementations of a large portion of pycodestyle
, for those that use Ruff without an autoformatter.
In this initial release, the rules are being introduced under a "nursery" flag, which requires that users explicitly select them (e.g., select = ["E111"]
); in other words, these rules are not yet enabled via select = ["E"]
.
If you're interested in testing the pycodestyle
rules, you can enable them via:
select = [
"E111", "E112", "E113", "E114", "E115", "E116", "E117",
"E201", "E202", "E203", "E211", "E221", "E222", "E223",
"E224", "E225", "E226", "E227", "E228", "E231", "E251",
"E252", "E261", "E262", "E265", "E266", "E271", "E272",
"E273", "E274", "E275",
]
These rules will be included as part of the E
category in a future release.
Breaking Changes
- [
pyupgrade
] Removekeep-runtime-typing
setting by @charliermarsh in #4427
Rules
- [
pylint
] Addduplicate-bases
rule by @alonme in #4411 - [
pylint
] FixPLW3301
auto-fix with generators by @JonathanPlasse in #4412 - [
flake8-async
] Implement flake8-async plugin by @qdegraaf in #4432 - [
pyupgrade
] Enable automatic rewrites oftyping.Deque
andtyping.DefaultDict
by @charliermarsh in #4420 - [
flake8-pyi
] Implementunannotated-assignment-in-stub
(PY052
) by @sladyn98 in #4293 - [
tryceratops
] Implement TRY302 -raise
afterexcept
by @john-h-k in #4461 - [
flake8-bandit
] Improve SQL injection detection logic (S608
) by @scop in #4499 - [
flake8-todos
] Implementflake8_todos
by @evanrittenhouse in #3921 - [
flake8-future-annotations
] Implementflake8-future-annotations
FA100 by @TylerYep in #3979 - Enable
pycodestyle
rules by @charliermarsh in #3689 - Enable
pycodestyle
rules under new "nursery" category by @charliermarsh in #4407
Settings
- Merge subsettings when extending configurations by @bendoerry in #4431
Bug Fixes
- Extend multi-line noqa directives to start-of-line by @charliermarsh in #4490
- Fix scoping of comprehensions within classes by @charliermarsh in #4494
- Enable autofix for split-assertions at top level by @charliermarsh in #4405
- Ignore ANN401 for overridden methods by @JonathanPlasse in #4409
- Fix
RUF010
autofix within f-strings by @JonathanPlasse in #4423 - Update C419 to be a suggested fix by @madkinsz in #4424
- Fix expected-indentation errors with end-of-line comments by @charliermarsh in #4438
- Emit non-logical newlines for "empty" lines by @charliermarsh in #4444
- Avoid emitting empty logical lines by @charliermarsh in #4452
- Avoid flagging missing whitespace for decorators by @charliermarsh in #4454
- Remove special-casing for whitespace-around-@ by @charliermarsh in #4458
- Avoid triggering
pd#at
and friends on non-subscripts by @charliermarsh in #4474 - Include precise tokens for extraneous-whitespace diagnostics by @charliermarsh in #4471
- Allow shebang comments at start-of-file by @charliermarsh in #4473
- Bring pycodestyle rules into full compatibility (on SciPy) by @charliermarsh in #4472
- Invert quote-style when generating code within f-strings by @charliermarsh in #4487
- Fix COM812 false positive in string subscript by @JonathanPlasse in #4493
- Overhaul sdist handling by @konstin in #4439
New Contributors
- @TylerYep made their first contribution in #3979
- @yanksyoon made their first contribution in #4428
- @bendoerry made their first contribution in #4431
- @qdegraaf made their first contribution in #4432
- @jameslamb made their first contribution in #4446
- @john-h-k made their first contribution in #4461
Full Changelog: v0.0.267...v0.0.269