Search

Friday, September 12, 2025

CS50 Python Project

 #### IP Calculator ####
 #### Description:
    This project created an IP calculator which takes an IP from the user then calculate subnet, gateway, mask, assigned VLAN and network realm. The user can enter as many IPs as they want until they decide to exit the program by Control + C on the keyboard. The data entered will be recorded in a CSV file and once the program is terminated, these data will be printed to a table format similar to the table below.

I could have started with standalone methods and a main function, but I really want to incorporate a class along with instance methods to demonstrate and cement what I learned in Lecture 8 - Object Oriented Programming. In addition, for the purpose of utilizing built-in libraries I'm using 'ipaddress' and 'rich', and their relevant objects - IPv4Network, IPv4Address from ipaddress and Table, Console from rich. In particular, Console is similar to 'print' but it allows me to print the network information in a table format.

Inititally I structured the nested try-except clauses in the class contructor but then I realize it's not a good practice to have many syntaxes there. The constructor should really be as simple as possible to just instantitate the object. Hence I decided to bring that block of code to a 'staticmethod' inside the class which seems to make the whole code much cleaner to read in my humble opinion.

Secondly, I was using regex 're.search' to find the pattern for the corresponding subnet from the IP provided by the user - see example below - but it does not look realistic in working environment and the regex is loose as '192.999.999.999' can still match.
if re.search(r"^192.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}", str(self.subnet)):
    self.vlan = 10
    self.network_name = 'Office Network'
As a result, I decided to utilize the existing 'ipaddress' for ranges.
if self.ip in IPv4Network("10.0.0.0/16"):
    self.subnet = IPv4Network("10.0.0.0/16")
    self.vlan = 10
    self.network_name = "Office"

def __str__(self) is used to print out the network details without using multiple prints. get_mask() and get_gw() is self-explanatory as they are built-in to the IPV4Network object.

def write_to_csv() is created to write the network information to a CSV file. Notice that output.tell() == 0 is there before the file is being written and it's basically a check to only write the defined headers only if the file is empty.

def print_table() uses both Table and Console object to write the network information in a table format. I define the title, the colors and name for each column in the table then read the csv file created previously to feed the data for Console to print the CS50 Networks table.

As mentioned above, def prompt_user() is just a static method inside the class to prompt the user to enter an IP address of their device until Control-C is pressed to exit the program gracefully. 'subnet' object is instantiated here 'subnet = CS50_Network(prompt)' and 'print(subnet)' triggers the call to the str method to print all the network details - see example below - then the data is stored in a csv file.
Your subnet is 10.2.0.0/18
Gateway is: 10.2.0.1
Subnet Mask is: 255.255.192.0
VLAN: 30
Network Name: Wireless
Invalid IP will pop up if the IP does not reside in any of the network blocked listed below the constructor and the program will reprompt the user for their device's IP. Once the user is done providing all their IPs, they can hit Control-C to exit the program. The table will be printed first before the program is gracefullly shut down.

In the main function, 'CS50_Network.prompt_user()' basically call the static method inside the class to kickstart the program. 

No comments:

Post a Comment