Skip to main content

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_scoping is not aware of the variables imported via from module import *, potentially raising false positives. The @block_scoping decorator doesn't have this issue.

  • Except for self in classes, ./check_block_scoping won'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

block_scoping-0.2.3.tar.gz (13.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

block_scoping-0.2.3-py3-none-any.whl (9.7 kB view details)

Uploaded Python 3

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

Hashes for block_scoping-0.2.3.tar.gz
Algorithm Hash digest
SHA256 030e499ecbe2c7732ec0a5c8b65a773d10c7a1af5c34c80b5eee91a3a236fb29
MD5 bd7395b3eaa382c977a1a83400ef5ab0
BLAKE2b-256 da01480efae62e1ed26d0a3a528cacd24dd0ac142f05d588e75e0878856eee01

See more details on using hashes here.

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

Hashes for block_scoping-0.2.3-py3-none-any.whl
Algorithm Hash digest
SHA256 00017870c5c6f5fbd671b77c4606e1e1dfaf88b9aa64056142423a7f1a63d2ca
MD5 a9ba7ed07eaec1b5be912d7ad342194d
BLAKE2b-256 9200339308d80c7f967c65763bd3fcd4eb294b0faff58764019cccc280a1fd8d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page