Hey there, fellow coders! Today, I want to share a neat little Python script that helps improve the quality of your code by adding type hints and enhancing type safety. This script utilizes the OpenAI API to analyze your Python files and make them more robust. Let’s dive into how it works!
Summary of the Code
This script, named helper_type_harden.py
, is designed to “harden” Python code by adding type hints and ensuring that the code adheres to stricter type checking. It can process a single file or an entire directory of Python files, making it quite versatile. The script uses the OpenAI API to get suggestions for improvements and can validate the syntax of the code after modifications.
Here’s the Code:
import argparse
import os
import shutil
import subprocess
import sys
import tempfile
import requests
api_key = os.environ.get("JIRA_AI_API_KEY")
endpoint = "https://api.openai.com/v1/chat/completions"
model = os.environ.get("JIRA_AI_MODEL")
def extract_code_from_output(output):
lines = output.splitlines()
code = None
for line in lines:
if line.startswith("```python"):
code = []
elif code is not None:
if line.startswith("```"):
continue
code.append(line)
return "\n".join(code)
def improve_text(prompt: str, text: str) -> str:
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
}
body = {
"model": model,
"messages": [
{"role": "system", "content": prompt},
{"role": "user", "content": text},
],
"temperature": 0.5,
}
response = requests.post(endpoint, json=body, headers=headers, timeout=120)
if response.status_code == 200:
return response.json()["choices"][0]["message"]["content"].strip()
else:
raise Exception("improve text not 200")
def validate_pycompile(file_path: str) -> bool:
try:
result = subprocess.run(
["python3", "-m", "py_compile", file_path], capture_output=True, text=True
)
if result.returncode != 0:
print(f"Syntax error in {file_path}: {result.stderr}")
return False
return True
except Exception as e:
print(f"Error validating {file_path}: {str(e)}")
return False
def harden_file(file_path: str, debug: bool, validate: bool):
with open(file_path, "r") as f:
source_code = f.read()
prompt = """
You are a Python expert focused on improving code quality and enhancing type safety.
Please review any python code given and add type hinting where appropriate,
Ensure that the code is type-hardened to enforce stricter type checking
and improve overall type safety. Don't create any new types.
Some type that may help:
from providers.ai_provider import AIProvider
from argparse import Namespace
from rest.client import JiraClient
from core.env_fetcher import EnvFetcher
from exceptions.exceptions import XXXX
from rest.client import JiraClient
from rh_jira import JiraCli
Respond with the updated code only. Do not include any explanations,
summaries, or additional comments.
"""
improved_code = improve_text(prompt, source_code)
improved_code = extract_code_from_output(improved_code)
# Create a temporary file to hold the improved code
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
temp_file.write(improved_code.encode("utf-8"))
temp_file_path = temp_file.name
if debug:
print(f"Improved code written to temporary file: {temp_file_path}")
if validate and not validate_pycompile(temp_file_path):
print("Python compilation validation failed. Not moving the file.")
os.remove(temp_file_path)
return
# If validation passed, replace the original file with the improved code
shutil.move(temp_file_path, file_path)
if debug:
print(f"File '{file_path}' has been successfully hardened.")
def process_directory(directory: str, debug: bool, validate: bool, recursive: bool):
for root, dirs, files in os.walk(directory):
for file in files:
if file.endswith(".py"):
file_path = os.path.join(root, file)
if debug:
print(f"Processing file: {file_path}")
harden_file(file_path, debug, validate)
if not recursive:
break
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Harden Python code using OpenAI API")
parser.add_argument("path", help="Path to the Python file or directory to harden")
parser.add_argument(
"--recursive", action="store_true", help="Recursively process directories"
)
parser.add_argument("--debug", action="store_true", help="Enable debug output")
parser.add_argument(
"--validate-pycompile",
action="store_true",
help="Validate Python syntax after improvements",
)
args = parser.parse_args()
if os.path.isdir(args.path):
process_directory(
args.path, args.debug, args.validate_pycompile, args.recursive
)
elif os.path.isfile(args.path):
harden_file(args.path, args.debug, args.validate_pycompile)
else:
print(f"Error: {args.path} is not a valid file or directory.")
sys.exit(1)
Explaining the Code
Let’s break down the key components of this script:
- Imports: The script imports several libraries such as
argparse
for command-line argument parsing,os
for file operations,shutil
for file manipulation,subprocess
for running commands, andrequests
for making HTTP requests. - Environment Variables: It retrieves the API key and model from environment variables, which are necessary for authenticating with the OpenAI API.
- Function Definitions:
extract_code_from_output(output)
: This function extracts the Python code from the output returned by the OpenAI API.improve_text(prompt, text)
: This function sends a request to the OpenAI API with a prompt to improve the provided text. If successful, it returns the improved code.validate_pycompile(file_path)
: This function checks if the Python file compiles without syntax errors.harden_file(file_path, debug, validate)
: This is the core function that reads a Python file, sends it for improvement, validates it, and replaces the original file if everything checks out.process_directory(directory, debug, validate, recursive)
: This function walks through a directory, processing each Python file it finds.
- Main Execution: The script uses
argparse
to handle command-line arguments, allowing users to specify a file or directory to process, whether to do it recursively, enable debug output, and validate the Python syntax after improvements.
This script is a fantastic tool for anyone looking to enhance their Python codebase. By adding type hints and ensuring code quality, you can catch potential issues early and improve maintainability.
So, if you’re looking to give your Python files a little TLC, give this script a try! It’s a simple yet powerful way to ensure your code is not only functional but also safe and clean.
Happy coding!
📚 Further Learning
🎥 Watch this video for more: