October 1, 2024
Clear code is essential for maintenance. While small programs are relatively simple, larger projects can become increasingly complex. Without proper formatting, code can become increasingly difficult to understand over time. Python Black is a tool that helps enforce a consistent style of code, making it easier to read and maintain.
Interested in learning Python? Read about: Keep Your Python Code Clean with CI/CD Linters
Black is a code formatter. A code formatter is a tool that automatically rearranges code to conform to a specific style guide. It can help improve code readability, consistency, and maintainability by enforcing consistent formatting rules. Black is a PEP 8 compliant opinionated formatter with its own style. As you can read in Black - read the docs “By using Black, you agree to cede control over minutiae of hand-formatting. In return, Black gives you speed, determinism, and freedom from pycodestyle nagging about formatting. You will save time and mental energy for more important matters”.
Coming back to our main question, is Black a linter? Well, the answer is NO. Linters are static code analysis tools that automatically checks source code for potential errors, stylistic problems, and programming bugs. Linters can write cleaner, more reliable, and maintainable code by identifying and flagging issues early in the development process.
As a Python hobbyist, it’s high time to have some fun and check out Black in action. For this fun I’ll use the code I presented in the post about converting images to Webp format (Convert Your Images To WebP with Python and Speed Up Your Website). The original code looks like this:
from pathlib import Path
from PIL import Image
def convert_to_webp(source):
destination = source.with_suffix(".webp")
image = Image.open(source) # Open image
image.save(destination, format="webp") # Convert image to webp
return destination
def main():
path_input = input("Provide source path:")
paths = Path(path_input).glob("**/*.png")
for path in paths:
webp_path = convert_to_webp(path)
print(webp_path)
return
if __name__ == '__main__':
main()
We’ll change it up a bit to give Black some work:
from pathlib import Path
from PIL import Image
def convert_to_webp(source):
destination = source.with_suffix(".webp")
image = Image.open(source) # Open image
image.save(destination,
format="webp") # Convert image to webp
return destination
def main():
path_input = input('Provide source path:')
paths = Path(path_input).glob("**/*.png")
for path in paths:
webp_path =
convert_to_webp(path)
print(
webp_path)
return
if __name__ == '__main__':
main()
After using black web.py, black couldn’t handle changing two lines:
webp_path =
convert_to_webp(path)
but after changing it to one line, as it was originally, Black reformatted the code to this:
from pathlib import Path
from PIL import Image
def convert_to_webp(source):
destination = source.with_suffix(".webp")
image = Image.open(source) # Open image
image.save(destination, format="webp") # Convert image to webp
return destination
def main():
path_input = input("Provide source path:")
paths = Path(path_input).glob("**/*.png")
for path in paths:
webp_path = convert_to_webp(path)
print(webp_path)
return
if __name__ == "__main__":
main()
We can see that Black formatter works properly and the code looks visually better.
Why not? Black can be used as a quality gate in the build process to ensure proper formatting quality – if we really care about it because of the possible increase in the number of failed builds which will certainly increase the cost of building (for credit plans). For this purpose we can use the --check option in Black. Let’s test it!
Let’s check with this simple example.py code:
def main():
for i in range(1, 11):
print(i)
return
if __name__ == '__main__':
main()
And just make a small change:
def main():
for i in range(1, 11):
print(i)
return
if __name__ == '__main__':
main()
After testing with black --check example.py the output is:
would reformat example.py
Oh no! 💥 💔 💥
1 file would be reformatted.
Let’s check the behaviour in the CI/CD pipeline using Travis CI. First let’s prepare our .travis.yml and test the usage of Black in our pipeline:
language: python
python:
- "3.8"
# Install dependencies
install:
- pip install black
jobs:
include:
- stage: formatter #this is our quality gate
script: black --check example.py
# Run the script
- stage: display
script:
- python example.py
And it works, here is our build log:
Lets create a quality gate with Black formatter, here is the .travis.yml:
language: python
python:
- "3.8"
# Install dependencies
install:
- pip install black
# Run the script
script:
- python -m black example.py
- python example.py
Here is what we see on our CI/CD tool Travis CI:
It works! In the first stage: “formatter” we create a quality gate, if the code is not formatted by Black the stage fails and the next stages will not be executed. This creates a great quality gate to avoid building (and maybe deploying) until the code will be formatted.
Python Black is a valuable tool for maintaining consistent code formatting in Python projects. While it’s not a linter, it can significantly improve code readability and maintainability by enforcing a specific style guide. By using Black, developers can save time and mental energy on formatting, allowing them to focus on more important aspects of their code. Additionally, integrating Black into CI/CD pipelines can act as a quality gate, ensuring that code meets formatting standards before being built or deployed. However, it’s important to note that Black has its own preferences and may not be able to handle all formatting scenarios automatically.
Python Black is a code formatter that automatically rearranges Python code to conform to a specific style guide. It helps improve code readability, consistency, and maintainability by enforcing consistent formatting rules.
While both Black and linters are used to improve code quality, they serve different purposes. Black focuses on formatting, ensuring code is consistently styled. Linters, on the other hand, analyze code for potential errors, stylistic problems, and programming bugs.
Yes, Python Black can be used as a quality gate in a CI/CD pipeline. By using the --check option, you can configure the pipeline to fail if the code doesn’t adhere to Black’s formatting rules. This helps ensure that only well-formatted code is merged into the main branch.
While Python Black is a powerful tool, it may not be able to handle all formatting scenarios automatically. In some cases, manual adjustments might be necessary to achieve the desired formatting. Additionally, Black’s style preferences may not align perfectly with everyone’s personal preferences.