Instructions
Requirements and Specifications
- A variable in python can contain any word character, [A-Za-z0-9_], but can’t begin with a digit. Find variable names that begin with digits. (Even cooler if you can exclude results between " or ' marks, to ignore strings That doesn’t have to be done using regex, though it can be.)
- Any variable in python followed by any number of spaces (including zero) and then an opening parenthesis can be assumed to be a function call or a function definition. Find any function calls to undefined functions.
- Find any function calls to defined functions that have the wrong number of arguments.
- Find situations where = has been used instead of ==. (Again, assume Foundations-level work; no need to go down too many rabbit holes for surprising uses. Consider if, elif, while, and return statements, and perhaps assigning Boolean values to variables like x = y == 3, which will set x to True or False based on the value of y.)
- Find situations where == has been used instead of =.
- Find situations where a method is called on a variable before that variable has been defined. (ie, a.append(3) before any line that says a = something, or a function definition where a is passed as an argument.)
- Find a situation where a student who is used to coding in Java maybe wrote some Java code in Python by mistake. Be specific about the situation you’re looking for. This should not be something as simple as looking for, like, the word “public” – it’s totally reasonable to make a variable that is just named “public” in Python!
- Global variables are often bad coding practice unless they are constants that are referenced without modification. Search for any global variables that are modified inside a function.
- Either in combination with the above bullet or separately, search for any local variables that are given the same name as global variables – also not an error, but inadvisable.
- Find indentation errors (that is, an increase in indentation level not preceded by something that forms a code block, or a decrease in indentation level that doesn’t match a prior indentation level.)
- Find missing colons.
- One, error_search.py, should behave as written above – search a Python file given in a command line argument for all of the mistakes you have chosen. For each one, print a line explaining the mistake you’re looking for, and then any line numbers of the given file that contain that error.
- The second, error_example.py, should contain a piece of Python code that you have modified to contain at least two instances of each mistake you’re searching for. In error_example.py, comment the lines that contain the mistakes, so I can open up the output from your error_search.py next to your error_example.py and compare them.
Source Code
ERROR EXAMPLE
var1 = 5
5var2 = 10 # This line contains a mistake
1var3 = 11 # This line contains a mistake
var = 14
for 100myVar in range(10): # This line contains a mistake
print(100myVar) # This line contains a mistake
if myVar = 100:
print("It is 100")
var == 5
myVar = 10
def methodTest(x):
return x+1
methodTest(myVar, myVar2)
undefinedMethodTest(myVar)
ERROR SEARCH
import re
import sys
def condition1(line, i):
"""
This function applies the following condition:
Check for variables name that begins with digits
"""
# Define the regex pattern
pattern = r'\d{1,}[A-Za-z]{1,}'
results = re.findall(pattern, line)
if len(results) > 0: # If there are matches, then show them with their line
for res in results:
print(f'ERROR at line {i+1} - Variable starts with number.\n\tVariable: {res}\n\tLine: {line}')
def condition2(line, i):
"""
This function applies the following condition:
Check for uses of = instead of ==
"""
# First, check if a line begins with if, elseif, while, do, etc
pattern1 = r'\b(if|elif|while)\b'
pattern2 = r'(?
if re.match(pattern1, line) and len(re.findall(pattern2, line)) > 0:
print(f'ERROR at line {i+1} - Missing equality/inequality symbol.\n\tLine: {line}')
def condition3(line, i):
"""
This function applies the following condition:
Check for uses of == instead of =
"""
# First, check if the line does not contais if, while, elif, etc
pattern1 = r'\b(if|elseif|while)\b'
pattern2 = r'(?
if not re.match(pattern1, line) and len(re.findall(pattern2, line)) > 0:
print(f'ERROR at line {i+1} - Extra equality/inequality symbol found.\n\tLine: {line}')
variables = list() # Store declared variables in a list
def condition4(line, i):
"""
This function applies the following condition:
Check if a method is called on a variable before it has been defined
"""
# Split line
data = line.strip().split('=')
if len(data) > 0:
var = data[0].strip()
if not ' ' in var and len(var) > 0 and not var in variables:
variables.append(var)
# Now, check if the line contains a function call
pattern = r'\(([^)]+)\)'
results = re.findall(pattern, line)
if len(results) > 0:
# Get variables and check if they have been declared
for res in results:
vars = res.split(',')
for v in vars:
v = v.strip()
if not v in variables:
print(f'ERROR at line {i+1} - A method is called on variable \'{v}\' which is not declared.\n\tLine: {line}')
methods = list() # Store declared methods in a list
def condition5(line, i):
"""
This function applies the following condition:
Find any calls of undefined methods/functions
"""
# First, check if the line contains parenthesis
if 'def' and ':' in line: # A method definition:
data = line.split(' ')
print(data)
data = data[1].split('(')
methodName = data[0].strip()
if not ' ' in methodName and not methodName in methods and len(methodName) > 0:
methods.append(methodName)
elif '(' in line and ')' in line:
# Split
data = line.split('(')
# Take the first part and split by space
data = data[0].split(' ')
if len(data) > 1:
methodName = data[-1]
else:
methodName = data[0]
methodName = methodName.strip()
if not methodName in methods: # the method is not declared
print(f'ERROR at line {i+1} - Undefined method \'{methodName}\'.\n\tLine: {line}')
if __name__ == '__main__':
"""This script reads a python file and find variable names that begin with a number
"""
# Check for command line arguments
if len(sys.argv) < 2:
print("Error: You must provide a filename.")
sys.exit(0)
# Define the regex pattern
pattern1 = r'\d{1,}[A-Za-z]{1,}'
# Open file
filename = sys.argv[1]
with open(filename, 'r') as f:
# Read lines
lines = f.readlines()
# Now, analyze each line
for i, line in enumerate(lines):
line = line.strip()
# Find pattern in line
condition1(line, i)
condition2(line, i)
condition3(line, i)
condition4(line, i)
condition5(line, i)