Highly opinionated: Spaces around `=` in multiline function calls
Project description
flake8-multilne-equals
A Flake8 plugin that enforces consistent spacing around = in function call keyword arguments, with different rules for single-line vs. multiline calls.
Installation
pip install flake8-multilne-equals
Motivation
This plugin improves code readability in multiline function calls by:
- Visual consistency: Spaces around
=in multiline calls make keyword arguments easier to scan - Better diffs: One argument per line produces cleaner git diffs when arguments change
- PEP 8 compliance: Maintains standard Python style (no spaces around
=) for single-line calls
This style deliberately contradicts PEP 8's E251 rule for multiline calls, trading strict adherence for improved readability in long function signatures.
Rules
MNA001: Missing spaces around = in multiline function call
Bad:
result = foo(
a=1,
b=2,
)
Good:
result = foo(
a = 1,
b = 2,
)
MNA002: Unexpected spaces around = in single-line function call
This rule replaces E251 for single-line calls.
Bad:
result = foo(a = 1, b = 2)
Good:
result = foo(a=1, b=2)
MNA003: Multiple arguments on same line in multiline function call
Bad - Multiple keyword arguments:
result = foo(
a = 1, b = 2,
c = 3,
)
Bad - Keyword mixed with positional:
result = foo(
1, 2, a = 3,
b = 4,
)
Good:
result = foo(
a = 1,
b = 2,
c = 3,
)
Configuration
Since this plugin contradicts PEP 8's E251, you need to configure Flake8 to ignore E251 and enable MNA checks.
Option 1: Command line
flake8 --extend-ignore=E251 your_file.py
Option 2: Configuration file
Create or edit .flake8 in your project root:
[flake8]
extend-ignore = E251
extend-select = MNA
Or in setup.cfg:
[flake8]
extend-ignore = E251
extend-select = MNA
Or in tox.ini:
[flake8]
extend-ignore = E251
extend-select = MNA
Option 3: pyproject.toml (requires flake8 >= 5.0)
[tool.flake8]
extend-ignore = ["E251"]
extend-select = ["MNA"]
Examples
Correct usage
# Single-line calls: no spaces around =
result1 = foo(a=1, b=2)
obj = MyClass(x=10, y=20, z=30)
# Multiline calls: spaces around =, one argument per line
result2 = foo(
a = 1,
b = 2,
c = 3,
)
result3 = MyClass(
x = 10,
y = 20,
z = 30,
)
# Positional args separate from keyword args
result4 = foo(
1,
2,
a = 3,
b = 4,
)
Common violations
# MNA002: Spaces in single-line call
result = foo(a = 1, b = 2)
# MNA001: No spaces in multiline call
result = foo(
a=1,
b=2,
)
# MNA003: Multiple keywords on same line
result = foo(a = 1, b = 2,
c = 3)
# MNA003: Keyword mixed with positional on same line
result = foo(1, 2, a = 3,
b = 4)
Editor Integration
VS Code
Install the Python extension and configure Flake8 in your settings.json:
{
"python.linting.flake8Enabled": true,
"python.linting.flake8Args": ["--extend-ignore=E251"]
}
PyCharm
- Go to Settings → Tools → External Tools
- Add Flake8 with arguments:
--extend-ignore=E251 $FilePath$ - Or configure in Settings → Editor → Inspections → Python → Flake8
Vim/Neovim
With ALE:
let g:ale_python_flake8_options = '--extend-ignore=E251'
Emacs
With Flycheck:
(setq flycheck-flake8rc ".flake8")
Then use a .flake8 config file.
Pre-commit Hook
Add to your .pre-commit-config.yaml:
repos:
- repo: https://github.com/PyCQA/flake8
rev: 6.1.0
hooks:
- id: flake8
args: ['--extend-ignore=E251']
additional_dependencies: ['/path/to/flake8-multiline-equals']
Development
Running tests
Create test files in test/ directory and run:
flake8 --extend-ignore=E251 [FILES]
Limitations
- The plugin only checks keyword arguments, not positional arguments
- Nested function calls are handled correctly, but deeply nested calls with complex line spans may have edge cases
- Multiline keyword argument values (e.g., lambda expressions, list comprehensions) only track the
=line, not the full value span
FAQ
Q: Why deviate from PEP 8?
A: While PEP 8 (E251) prohibits spaces around = in keyword arguments, this plugin prioritizes readability for multiline calls. The spaces create visual separation that makes complex function signatures easier to read and modify.
Q: Can I use this with other formatters like Black?
A: Black does not add spaces around = in keyword arguments, so it conflicts with this plugin's MNA001 rule. You would need to manually format multiline calls or configure Black to skip those sections.
Q: What if I only want to enforce the "one argument per line" rule (MNA003)?
A: You can selectively ignore rules in your Flake8 config:
[flake8]
extend-ignore = E251, MNA001, MNA002
extend-select = MNA
Q: Does this work with Python 2?
A: No, this plugin requires Python 3.9+ for type hints and AST features.
License
MIT License - see LICENSE file for details.
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all checks pass
- Submit a pull request
Changelog
1.0.0 (2024-12-13)
- Initial release
- MNA001: Enforce spaces around
=in multiline calls - MNA002: Prohibit spaces around
=in single-line calls - MNA003: One argument per line in multiline calls
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flake8_multiline_equals-1.1.0.tar.gz.
File metadata
- Download URL: flake8_multiline_equals-1.1.0.tar.gz
- Upload date:
- Size: 10.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4d38682f6053fe17e9daf573d81becd3a15514ab7a584290cd5dadc6b2fd566f
|
|
| MD5 |
0ca79686a1c809d270879b3d8237d7d7
|
|
| BLAKE2b-256 |
3e256cfe0ecd7f2e0a73450a9ce683688ebf916ebd34f6a3f9fe72cdb788070f
|
File details
Details for the file flake8_multiline_equals-1.1.0-py3-none-any.whl.
File metadata
- Download URL: flake8_multiline_equals-1.1.0-py3-none-any.whl
- Upload date:
- Size: 8.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
714dca3e8eecc93ce0ff8105aa268d110a12590a7164d34578c934f5448c490f
|
|
| MD5 |
4695477020f2ecf00341d845b492885f
|
|
| BLAKE2b-256 |
b6676eab7278b7e94a9261901142f313eac7b0b7a4c1b80fb016e9bdbf89f943
|