A simple package for block scoping
Project description
Block Scoping
This is simple PyPi package running static analysis to detect scoping issues caused by Python's lack of block scoping.
Python's scoping is a common source of bugs.
Example
total = 0
for item in items:
if item > 0:
total += item
else:
skipped = True
if skipped:
print("Some items have been skipped")
The mistake is easy to spot. However, in larger codebases, such issues can be much harder to detect.
Another Example
try:
x = int(y)
f(x)
except:
logging.error(f"error when x = {x}")
The intent is to catch errors raised by f, but this could also catch errors raised by int(y), which this except is not prepared for.
To avoid these potential bugs, it's safer not to reference any variable in the except block that was defined within the try block. A simple fix would be:
x = None
try:
x = int(y)
f(x)
except:
logging.error(f"error when x = {x}")
This package helps you identify these issues before execution, for example by automatically checking your code in your CI/CD script.
To check your code, install the package and run:
./check_block_scoping your_dir/*.py
or
./check_block_scoping your_dir --exclude notthis.py notthat.py
This will recursively search your_dir.
You can opt-out specific functions and classes by decorating them with @no_block_scoping.
Alternatively, you can explicitly opt-in with @block_scoping, which removes the need to run ./check_block_scoping altogether, especially if you want to enforce scoping rules more strictly across your organization, or only at specific locations.
Rules
The package implements the following rules:
| Control Flow | Scope of variables defined inside block |
|---|---|
| If/Elif/Else | block only, unless assigned in all branches |
| For loop | block only |
| While Loop | block only |
| Walrus assignment | block only if used in an if or a while |
with block_scope() |
block only |
Other with statements |
variables outlive their block |
| Try/Else/Finally | Try/Else/Finally: outlive their block but can't be used in Except |
| Except | block only |
| Case (Python >= 3.10) | block only |
This applies to:
- all variables,
- all attributes of
self.
Specifically, you are only allowed to use an attribute of self if the attribute is defined in the constructor.
with statements do not create block scopes. This is because in 99% of cases, the intent of a with statement is for its block to always be executed, unlike if/while/try which are designed for the opposite.
This is why the special object block_scope was added.
with block_scope():
x = 3
print(x) # this package counts this as an error
Known Issues
-
./check_block_scopingis not aware of the variables imported viafrom module import *, potentially raising false positives. The@block_scopingdecorator doesn't have this issue. -
Except for
selfin classes,./check_block_scopingwon't detect scoping issues that involve object attributes.
External Contribution
Contributions are welcomed!
Project details
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 block_scoping-0.2.3.tar.gz.
File metadata
- Download URL: block_scoping-0.2.3.tar.gz
- Upload date:
- Size: 13.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
030e499ecbe2c7732ec0a5c8b65a773d10c7a1af5c34c80b5eee91a3a236fb29
|
|
| MD5 |
bd7395b3eaa382c977a1a83400ef5ab0
|
|
| BLAKE2b-256 |
da01480efae62e1ed26d0a3a528cacd24dd0ac142f05d588e75e0878856eee01
|
File details
Details for the file block_scoping-0.2.3-py3-none-any.whl.
File metadata
- Download URL: block_scoping-0.2.3-py3-none-any.whl
- Upload date:
- Size: 9.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
00017870c5c6f5fbd671b77c4606e1e1dfaf88b9aa64056142423a7f1a63d2ca
|
|
| MD5 |
a9ba7ed07eaec1b5be912d7ad342194d
|
|
| BLAKE2b-256 |
9200339308d80c7f967c65763bd3fcd4eb294b0faff58764019cccc280a1fd8d
|