Break from multiple loops at once in Python
Project description
breakall
Break from multiple loops at once in Python
Why isn't this a thing in Python?
Index
- Break from multiple loops at once in Python
- Index
- Getting Started
- Keyword
- Linter and Type Checker Configuration
- Command-Line Interface
- Deployment
- Contributing
- Authors
- Disclaimer
- License
Getting Started
Prerequisites
You will need Python +3.10 to run this module
# vermin output
Minimum required versions: 3.10
Incompatible versions: 2
[!NOTE]
The heavy use ofast.unparsemakes this incompatible with Python version lower than 3.10
Installation
pip install git+https://github.com/Animenosekai/breakall.git
Basic Usage
You can use breakall by decorating your function with @enable_breakall:
>>> from breakall import enable_breakall
>>>
>>> @enable_breakall
... def main():
... for i in range(10):
... for j in range(10):
... for k in range(10):
... if k == 5:
... breakall
... print(i, j, k)
Alternatively, you can enable breakall for all functions in your module by calling enable_breakall() without arguments:
from breakall import enable_breakall
def main():
for i in range(10):
for j in range(10):
for k in range(10):
if k == 5:
breakall
print(i, j, k)
# This will enable breakall for all functions in the current scope
enable_breakall()
main()
Or you can use the command-line interface:
python -m breakall script.py
# or
breakall script.py
This will automatically enable breakall for all functions in the file.
Keyword
You can use breakall to break from multiple loops at once.
There is different syntax to determine how many loops to break from.
breakall
The breakall keyword will break from all loops in the current scope.
>>> from breakall import enable_breakall
>>>
>>> @enable_breakall
... def test():
... for i in range(3):
... for j in range(3):
... if j == 1:
... breakall
... print(f" ({i}, {j})")
... print(f" End of i={i}")
... print("Done")
>>>
>>> test()
(0, 0)
Done
As you can see, the loops are completely exited without printing the rest of the iterations or "End of i={i}" message.
breakall: n
The breakall: n keyword will break from n loops in the current scope.
>>> from breakall import enable_breakall
>>>
>>> @enable_breakall
... def test():
... for i in range(3):
... for j in range(3):
... for k in range(3):
... if k == 1:
... breakall: 2
... print(f" ({i}, {j}, {k})")
... print(f" End of j={j}")
... print(f"End of i={i}")
... print("Done")
>>>
>>> test()
(0, 0, 0)
End of i=0
(1, 0, 0)
End of i=1
(2, 0, 0)
End of i=2
Done
In this example, breakall: 2 breaks from the innermost two loops (the j and k loops), but the outermost i loop continues.
breakall @ n
The breakall @ n keyword will break from all loops up to and including the n-th loop from the inside.
>>> from breakall import enable_breakall
>>>
>>> @enable_breakall
... def test():
... for i in range(3): # Loop 1
... for j in range(3): # Loop 2
... for k in range(3): # Loop 3
... if k == 1:
... breakall @ 2
... print(f" ({i}, {j}, {k})")
... print(f" End of k loop")
... print(f"End of j loop")
... print("Done")
>>>
>>> test()
(0, 0, 0)
(1, 0, 0)
(2, 0, 0)
Done
In this example, breakall @ 2 targets loop 2 (the j loop), so it breaks from both loop 3 (k) and loop 2 (j), but loop 1 (i) continues.
[!NOTE] The
breakall @ nkeyword is 1-indexed, where 1 is the innermost loop
Linter and Type Checker Configuration
When using breakall, certain linting and type-checking tools may report false positives since they don't understand the breakall statement transformation.
Importing breakall
You can import the breakall statement to make your type checker happy, but it is not necessary for the code to work:
from breakall import breakall
def hello():
for i in range(n):
for j in range(m):
if j == 1:
breakall
print(i, j)
Ruff
Add to your module using breakall:
# ruff: noqa: B018, F842
Where:
B018- Useless expression (for barebreakallstatements)F842- Local variable name is assigned to but never used (forbreakall: nstatements where the loop counter variable is not used)
Pyright
Add to your module using breakall:
# pyright: reportUnusedExpression=false, reportUnusedVariable=false, reportGeneralTypeIssues=false
Where:
reportUnusedExpression=false- Allow unused expressions (forbreakallstatements)reportUnusedVariable=false- Allow unused variables (forbreakall: nstatements where the loop counter variable is not used)reportGeneralTypeIssues=false- Suppress general type issues that may when usingbreakall: nstatements (nis an integer, not a type)
Command-Line Interface
You can use the breakall module directly from the command line without decorating functions:
python -m breakall script.py
The CLI automatically applies enable_breakall to all functions in the target file:
# my_script.py
def nested_loops():
for i in range(3):
for j in range(3):
if j == 1:
breakall
print(f" ({i}, {j})")
print(f" End of i={i}")
print("Done")
nested_loops()
$ python -m breakall my_script.py
(0, 0)
Done
Tracing Imported Modules
By default, the CLI only applies enable_breakall to functions in the main file. If you're using breakall in imported modules, use the --trace flag:
python -m breakall script.py --trace
Example: Without --trace
If your imported module contains breakall, it will fail without --trace:
# helper.py
def helper_function():
for i in range(3):
for j in range(3):
if j == 1:
breakall
print(f" ({i}, {j})")
print(f" End of i={i}")
print("Done")
# main.py
from helper import helper_function
helper_function()
$ python -m breakall main.py
(0, 0)
Traceback (most recent call last):
File "main.py", line 3, in <module>
helper_function()
File "helper.py", line 6, in helper_function
breakall
NameError: name 'breakall' is not defined
Example: With --trace
Using --trace enables import hooking, so all imported modules support breakall:
$ python -m breakall main.py --trace
(0, 0)
Done
The --trace flag automatically applies the enable_breakall decorator to all functions in imported modules, allowing them to use the breakall statement.
Saving Transformed Code
You can save the transformed Python code to a file using the --output option:
python -m breakall script.py --output transformed.py
This generates a new file with all breakall statements converted to proper loop-breaking logic.
Deployment
This module is currently in development and might contain bugs.
Feel free to use it in production if you feel like it is suitable for your production even if you may encounter issues.
Contributing
Pull requests are welcome. For major changes, please open an discussion first to discuss what you would like to change.
Please make sure to update the tests as appropriate.
Authors
- Anime no Sekai - Initial work - Animenosekai
Disclaimer
This project is not affiliated with the Python Software Foundation.
License
This project is licensed under the MIT License - see the LICENSE file for details
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 breakall-1.0rc1.tar.gz.
File metadata
- Download URL: breakall-1.0rc1.tar.gz
- Upload date:
- Size: 738.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bf1802e7e250066024f911a8072177cd0f7bce7a5a6bbb3df0b631f03692c342
|
|
| MD5 |
2e022d484df8b1321f59d838e852a349
|
|
| BLAKE2b-256 |
84ed2e65b015545a5a6b9d37853520e0cfc848b50e53b790e8628a8dda9cc00f
|
File details
Details for the file breakall-1.0rc1-py3-none-any.whl.
File metadata
- Download URL: breakall-1.0rc1-py3-none-any.whl
- Upload date:
- Size: 19.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e8daad311158e3337e76c8d2794197ecaf468a93f224144baec3ef2e05e33cff
|
|
| MD5 |
e483419c3a92668d0f107c7c2f043297
|
|
| BLAKE2b-256 |
53ae7eb28d0c94c3116aba1bbe439cadae09085f06c50e182fa1ffd2e7eb8631
|