Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

Assignment 2: Objective: practice Python programming with string processing, collections, and file I/O Understanding a large program usually requires knowledge of the calling relationships between

image text in transcribed

Assignment 2:

Objective: practice Python programming with string processing, collections, and file I/O

Understanding a large program usually requires knowledge of the calling relationships between functions or methods as well as dependencies between their larger units of modularization, such as classes. Oftentimes, when we're trying to study function FA, we need to know which other functions call it. And if there are numerous calling functions, we sometimes just need to know which classes they belong to, for future investigation.

In this programming assignment, the input is a text file with the following format:

C1.f1 calls C1.f2 C1.f3 calls C1.f2 C2.f4 calls C1.f3 C2.f4 calls C2.f5 C2.f4 calls C3.f1 C1.f1 calls C1.f1 C2.f5 calls C3.f1

That is, each line tells you which function calls which other function, as qualified by their class name. Similar to Java, functions in different classes may have the same names, hence the class qualifier. Note that, as in the second to last line, a function might call itself. For the purpose of this project, assume that all lines will be of this format: ClassA.functionB calls ClassX.functionY, that is, each function listed is part of a class.

Requirements:

Your program will read the file and store the relationships in a collection structure. It is up to you to determine the proper collection(s) to use.

Next, your program will output the following reports to standard output:

Called by relationships - list which functions call a given function, in a format like this:

Called by relationships: C1.f1 is called by C1.f1 C1.f2 is called by C1.f1,C1.f3 C1.f3 is called by C2.f4 C2.f4 is not called by any function C2.f5 is called by C2.f4 C3.f1 is called by C2.f4,C2.f5

If a function is called from multiple functions, each of those calling functions are listed in a comma-separated format. Note that this output should be sorted alphabetically.Class dependencies - list which class uses functions from which other class, like this:

Class dependencies: C2 uses C1,C3

If a class uses multiple classes, each of those are listed in a comma-separated format. Note that self relationships are excluded from this list (so you won't see C1 uses C1 or C2 uses C1, C2, C3 and so on) since that is nearly true with every class usually having functions that call other functions inside it.Class reverse dependencies - this is the reverse relationship from the previous output. List which class are used by other classes, like this:

Class reverse dependencies: C1 is used by C2 C3 is used by C1

As in the previous output, self relationships (e.g., C2 is used by C2) are excluded from this list. If a class is used by multiple classes, each of those are listed in a comma-separated format.

Additional Requirements

Handle exceptions for incorrect input format. For example, the following lines should be flagged:

C1 calls C2.f2 # C1 is missing a function C1.f1 # does not call anything C1.f1.f2 calls C3.f3 # multiple qualifiers on f2

Just print the error as incorrect input line with the line itself and ignore the line in subsequent processing.

There should be at least 2 classes, a DataExtractor class that includes responsibilities for reading the file and putting the inputs into an appropriate collection, and a GraphAnalysis class that performs the necessary analysis of the input data and produces the 3 outputs outlined above. Optionally, the actual generation of outputs can also be separated into its own class. You can define more classes than these according to your design preference.

Include a docstring for each major function you create explaining what its responsibilities are.

Submit one Python file for each class as well as a separate Python file that calls these, and your own test data file with at least 10 valid lines.

Code:

class DataExtractor:

def __init__(self, filename):

self.filename = filename

def load_data(self):

data = []

# open the file and read each line

with open(self.filename, 'r') as f:

for line in f:

# split the line into the two components

parts = line.split(' calls ')

if len(parts) != 2:

# invalid format

print('Incorrect input line: {}'.format(line))

continue

caller, callee = parts

# append the data to the list

data.append((caller, callee))

return data

GraphAnalysis.py

"""

This class is responsible for analyzing the input graph

and generating the 3 reports outlined in the problem.

"""

class GraphAnalysis:

def __init__(self, data):

self.data = data

def called_by_relationships(self):

# create a dict to store the data

d = {}

# iterate through the data

for caller, callee in self.data:

# update the dict

if callee in d:

d[callee].append(caller)

else:

d[callee] = [caller]

# print the report

print('Called by relationships:')

for callee, callers in d.items():

# sort the callers

callers.sort()

# convert to comma-separated string

callers = ', '.join(callers)

print('{} is called by {}'.format(callee, callers))

def class_dependencies(self):

# create a set to store the data

s = set()

# iterate through the data

for caller, callee in self.data:

# extract the classes

caller_class, callee_class = caller.split('.')[0], callee.split('.')[0]

# add to the set

if caller_class != callee_class:

s.add((caller_class, callee_class))

# print the report

print('Class dependencies:')

for caller_class, callee_class in sorted(s):

print('{} uses {}'.format(caller_class, callee_class))

def class_reverse_dependencies(self):

# create a dict to store the data

d = {}

# iterate through the data

for caller, callee in self.data:

# extract the classes

caller_class, callee_class = caller.split('.')[0], callee.split('.')[0]

# update the dict

if callee_class in d:

d[callee_class].append(caller_class)

else:

d[callee_class] = [caller_class]

# print the report

print('Class reverse dependencies:')

for callee_class, caller_classes in d.items():

# remove self relationships

if callee_class in caller_classes:

caller_classes.remove(callee_class)

# sort the callers

caller_classes.sort()

# convert to comma-separated string

caller_classes = ', '.join(caller_classes)

print('{} is used by {}'.format(callee_class, caller_classes))

main.py

"""

This file is responsible for calling the DataExtractor and

GraphAnalysis classes to produce the desired output.

"""

from DataExtractor import DataExtractor

from GraphAnalysis import GraphAnalysis

if __name__ == '__main__':

# create the DataExtractor

de = DataExtractor('input.txt')

# load the data

data = de.load_data()

# create the GraphAnalysis

ga = GraphAnalysis(data)

# generate the reports

ga.called_by_relationships()

ga.class_dependencies()

ga.class_reverse_dependencies()

input.txt

C1.f1 calls C1.f2

C1.f3 calls C1.f2

C2.f4 calls C1.f3

C2.f4 calls C2.f5

C2.f4 calls C3.f1

C1.f1 calls C1.f1

C2.f5 calls C3.f1

(the example from Programming Assignment 2 with a duplicate entry in line 4), the program should yield the same outputs as before. Write at least one test case for each scenario. Fix the code if the test fails. Notes: 1. Put the test cases in a separate file. It is a good programming practice to separate the test code so it eventually does not get pulled into the production code. 2. You will need to read ahead to the chapter on unit testing which will be covered in Reading Assignment 10. 3. To simplify your work, you don't have to worry about complete code coverage (exercising every statement in the program). For example, scenario 2 has several different situations - just test for one of them. 4. As you reexamine your code in Programming Assignment 2, consider also opportunities to make the code more Pythonic by making use of comprehensions and iterables. Conceivably, you can use a generator to create some random test data also. These are all optional improvements, and good practice as a Python programmer

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Database Processing

Authors: David J. Auer David M. Kroenke

13th Edition

B01366W6DS, 978-0133058352

More Books

Students also viewed these Databases questions

Question

Does it avoid using personal pronouns (such as I and me)?

Answered: 1 week ago

Question

Does it clearly identify what you have done and accomplished?

Answered: 1 week ago