Last active
December 18, 2015 02:28
-
-
Save luciomartinez/5710766 to your computer and use it in GitHub Desktop.
Persons is a CLI Unix system wrote in Python. This application offer the possibility to create, edit, save and remove information with a command line interface.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
# | |
# __init__.py | |
#~ | |
#~ This file is part of Persons. | |
#~ | |
#~ Persons Copyright © 2013 Lucio | |
#~ | |
#~ This is free software, and you are welcome to redistribute it | |
#~ under certain conditions; | |
#~ see <http://ubuntuone.com/6lIaO1Ei1AH7zAMU1bYVw5> for details. | |
#~ This program comes with ABSOLUTELY NO WARRANTY; | |
#~ for details see <http://ubuntuone.com/6lIaO1Ei1AH7zAMU1bYVw5>. | |
#~ | |
#~ You should have received a copy of the GNU General Public License | |
#~ along with this program. If not, see <http://www.gnu.org/licenses/>. | |
import os | |
from Persons import Persons | |
from GetChar import GetchUnix | |
# Enter all the persons that the user want to | |
def enter_persons(persons): | |
# The user will add many users as he wants to | |
user_response = "y" | |
while (user_response=='y')|(user_response=='Y'): | |
# Clear the terminal screen | |
os.system('clear') | |
print "Registering a new person.." | |
name = raw_input(" Enter the name: ") | |
age = raw_input(" Enter the age: ") | |
email = raw_input(" Enter the email: ") | |
# Add the given values to the object node | |
success = persons.add(name, age, email) | |
if not success: | |
print "\nThe values entered are incorrect. This information could not be saved." | |
else: | |
print "\nThe new person was added successfully!" | |
user_response = raw_input("""\nIf you want to add another person enter 'Y', | |
otherwise enter any character else.. """) | |
# Clear the screen before exit from the method | |
os.system('clear'); | |
# Show every person in the list | |
def show_persons(persons): | |
top = persons.amount() | |
if top > 0: | |
for i in range(top): | |
print "Person number %d:"%(i+1) | |
print(" - Name: " + persons.get_name(i)) | |
print(" - Age: " + str(persons.get_age(i))) | |
print(" - E-mail: " + persons.get_email(i)) | |
else: | |
print "There are no persons on the list." | |
def remove_person(persons): | |
getch = GetchUnix() | |
os.system('clear') | |
name = raw_input("Enter the name of the required person: ") | |
index = persons.get_persons_with_name(name) | |
top = len(index) | |
if top == 0: | |
print "There are no persons with the name entered." | |
else: | |
print "Persons that match the entered name: " | |
for i in range(top): | |
print "\nPerson number %d:"%(i+1) | |
print " - Name: " + persons.get_name(index[i]) | |
print " - Age: " + str(persons.get_age(index[i])) | |
print " - E-mail: " + persons.get_email(index[i]) | |
print "\nNow you need to enter the number of the person" | |
print "that you want to remove from the list." | |
try: | |
pos = int(raw_input("Person's number: ")) | |
except ValueError: | |
pos = 0 | |
if 0 < pos <= top: | |
email = persons.get_email(index[pos-1]) | |
res = persons.remove_person_by_email(email) | |
if not res: | |
print "ERROR: the selected person could not be removed." | |
else: | |
print "The selected person was successfully removed!" | |
else: | |
print "ERROR: invalid index." | |
getch() | |
def save_information(persons, path): | |
getch = GetchUnix() | |
if persons.amount() > 0: | |
print """What do you want to do: | |
1 - ERASE all the actual information of the file and save there. | |
2 - ADD the actual information to the information of file appending. | |
3 - Go back to the menu and don't save anything.""" | |
user_response = raw_input("Enter 1 or 2 or 3 to choice one option: ") | |
if (user_response=='1')|(user_response=='2'): | |
if user_response == '1': | |
res = persons.save_to_file(path, True) | |
elif user_response == '2': | |
res = persons.save_to_file(path) | |
if res: | |
print "All the information was saved successfully!" | |
else: | |
print "ERROR: the information could not be saved." | |
else: | |
print "Nothing has been saved.." | |
else: | |
print "There are no persons to save!" | |
getch() | |
def load_information(persons, path): | |
getch = GetchUnix() | |
print """What do you want to do: | |
1 - ERASE all the actual information and load the information from the file. | |
2 - ADD the information from the file to the actual information | |
3 - Go back to the menu and don't modify anything""" | |
user_response = raw_input("Enter 1 or 2 or 3 to choice one option: ") | |
if (user_response=='1')|(user_response=='2'): | |
if user_response == '1': | |
res = persons.load_from_file(path, True) | |
elif user_response == '2': | |
res = persons.load_from_file(path) | |
if res: | |
print "All the information was loaded successfully!" | |
else: | |
print "ERROR: the information could not be loaded." | |
else: | |
print "Nothing has been modified.." | |
getch() | |
def confirm_reset(persons): | |
'''Request a confirmation to the user, | |
to proceed to remove all the information. | |
It wont modify any local file | |
''' | |
getch = GetchUnix() | |
print "Are you sure that you want to remove all the persons from the actual list?" | |
print "NOTE: this wont modify any local file.\n" | |
user_response = raw_input("Enter 1 to confirm or anything else to cancel: ") | |
if user_response == '1': | |
persons.clear_all() | |
print "The information was removed successfully!" | |
else: | |
print "Nothing has been modified.." | |
getch() | |
def show_menu(persons, path): | |
# Instantiate the class so we can then call the method | |
getch = GetchUnix() | |
os.system('clear') | |
print """The following actions are available: | |
1 - Add persons to the list | |
2 - Show the content of the list | |
3 - Save the list on an external file | |
4 - Load the persons from an external file | |
5 - Remove a specific person from the list | |
6 - Clear all the list | |
10 - Exit the application | |
""" | |
user_response = raw_input("Enter the number of the desire option.. ") | |
os.system('clear') | |
if user_response == '1': | |
enter_persons(persons) | |
elif user_response == '2': | |
show_persons(persons) | |
getch() | |
elif user_response == '3': | |
save_information(persons, path) | |
elif user_response == '4': | |
load_information(persons, path) | |
elif user_response == '5': | |
remove_person(persons) | |
elif user_response == '6': | |
confirm_reset(persons) | |
elif user_response == '10': | |
return False | |
else: | |
raw_input("You need to enter a valid number!") | |
# If returns true, then it should be called again | |
return True | |
def main(): | |
# This is presumming that there is a folder called 'data' | |
# on the parent directory, containing the file 'data.list' | |
# In this file will be saved and loaded the persons. | |
path = os.path.normpath(os.getcwd()+'/../'+'data')+'/data.list' | |
persons = Persons() | |
# When the function returns false, | |
# then the program will finish. | |
# Otherwise, it will show the menu again | |
while show_menu(persons, path): | |
pass | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#~ Created by Danny Yoo on Fri, 21 Jun 2002 | |
#~ Under the PSF license | |
#~ http://code.activestate.com/recipes/134892/ | |
class GetchUnix: | |
def __init__(self): | |
import tty, sys | |
def __call__(self): | |
import sys, tty, termios | |
fd = sys.stdin.fileno() | |
old_settings = termios.tcgetattr(fd) | |
try: | |
tty.setraw(sys.stdin.fileno()) | |
ch = sys.stdin.read(1) | |
finally: | |
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) | |
return ch | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
# | |
# __init__.py | |
#~ | |
#~ This file is part of Persons. | |
#~ | |
#~ Persons Copyright © 2013 Lucio | |
#~ | |
#~ This is free software, and you are welcome to redistribute it | |
#~ under certain conditions; | |
#~ see <http://ubuntuone.com/6lIaO1Ei1AH7zAMU1bYVw5> for details. | |
#~ This program comes with ABSOLUTELY NO WARRANTY; | |
#~ for details see <http://ubuntuone.com/6lIaO1Ei1AH7zAMU1bYVw5>. | |
#~ | |
#~ You should have received a copy of the GNU General Public License | |
#~ along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# Necessary for the regular expressions | |
import re | |
class Persons: | |
def __init__(self): | |
self.persons = [] | |
def get_name(self, index): | |
'''Returns a string with the name of the person | |
that is on the index position (starts at zero). | |
If the index is invalid, return an empty string (""). | |
''' | |
try: | |
return self.persons[index][0] | |
except IndexError: | |
return "" | |
def get_age(self, index): | |
'''Returns an integer with the age of the person | |
that is on the index position (starts at zero). | |
If you want to handle the returned value as a string, | |
put it inside the str() function. | |
If the index is invalid, return zero (0). | |
''' | |
try: | |
return self.persons[index][1] | |
except IndexError: | |
return 0 | |
def get_email(self, index): | |
'''Returns a string with the e-mail of the person | |
that is on the index position (starts at zero). | |
If the index is invalid, return an empty string (""). | |
''' | |
try: | |
return self.persons[index][2] | |
except IndexError: | |
return "" | |
def get_position_by_email(self, email): | |
'''Receives a string and return the position | |
of the persons that have this email. | |
If no person have this email, then will return -1. | |
''' | |
top = self.amount() | |
if top > 0: | |
for i in range(top): | |
if self.get_email(i) == email: | |
return i | |
return -1 | |
def is_email_on_list(self, email): | |
'''Check if the email is already on the list. | |
Returns false if it does not. | |
''' | |
top = self.amount() | |
if top > 0: | |
for i in range(top): | |
if self.get_email(i) == email: | |
return True | |
# Reached if the email is not on the list | |
return False | |
def add(self, name, age, email): | |
'''Add a new person to the list. | |
The age must be an integer value, or a string that can be converted. | |
The email cannot be on the list. Making this an unique field. | |
Returns true when success, or false if values entered are incorrect. | |
''' | |
try: | |
if (not self.__validate_email(email)) | (not self.__validate_name(name)) | (1<int(age)<120) | (self.is_email_on_list(email)): | |
return False | |
self.persons.append((name, int(age), email)) | |
return True | |
except ValueError: | |
return False | |
def amount(self): | |
'''Returns an integer with the amount of persons (items) | |
that are on the list. | |
''' | |
return len(self.persons) | |
def get_persons_with_name(self, name): | |
'''Return a list of integers with indexs. | |
Each index will be the position of a person that his name | |
match with the given name or a part of this string. | |
''' | |
# This list will contain integers | |
newlist = [] | |
top = self.amount() | |
if top > 0: | |
for i in range(top): | |
if self.get_name(i).find(name) == 0: | |
# The name (or a part of this) is on the node | |
# Then we add their index to the new list | |
newlist.append(i) | |
return newlist | |
def clear_all(self): | |
'''Clear the list, removing all the information there. | |
''' | |
self.persons = [] | |
def remove_person_by_email(self, email): | |
'''Remove a specific person from the list. | |
To separate this person from every one else, | |
this function receive the email (an unique value). | |
If the person was successfully removed, then return true. | |
''' | |
position = self.get_position_by_email(email) | |
if position > -1: | |
self.persons.pop(position) | |
return True | |
return False | |
def save_to_file(self, path, create=False): | |
'''Save all the persons of the list in a CVS text file. | |
This function receives the path to the file, | |
and (optinally) a boolean: | |
- if false (default): append the information in the existent (or new) file. | |
- if true: create (and overwrite if necessary) the file. | |
If operation completed successfully, | |
then it returns true, else it returns false. | |
''' | |
try: | |
if not create: | |
f = open(path, 'a') | |
else: | |
f = open(path, 'w') | |
top = self.amount() | |
for i in range(top): | |
f.write(self.get_name(i) + ", " + str(self.get_age(i)) + ", " + self.get_email(i) + '\n') | |
f.close() | |
return True | |
except IOError: | |
return False | |
def load_from_file(self, path, create=False): | |
'''Read all the persons contained in a CVS text file. | |
This function receives the path to the file, | |
and (optionally) a boolean: | |
- if false (default): add all the persons of the file | |
at the end of the actual list. | |
- if true: all the persons in the actual list will be removed, | |
and it will create a new list with the persons of the file. | |
If operation completed successfully, | |
then it returns true, else it returns false. | |
''' | |
if create: | |
# Clear the list | |
self.clear_all() | |
try: | |
f = open(path, 'r') | |
for line in f: | |
first_divisor = line.index(',') | |
second_divisor = self.__find_nth(line,",") | |
# Save the three values on independent variables | |
name = line[0 : first_divisor] | |
age = line[first_divisor+2 : second_divisor] | |
email = line[second_divisor+2 : len(line)-1] | |
# Add the variable's values to the list | |
self.persons.append((name, age, email)) | |
f.close() | |
return True | |
except IOError: | |
return False | |
except ValueError: | |
return False | |
#~ The following methods are internal and it should not be | |
#~ instantiated, called nor even mentioned from an external scope! | |
#~ Lets keep this as a secret :) | |
def __find_nth(self, str1, substr1): | |
'''Internal function that returns the position | |
of the second appearance of the substring on the string. | |
This method should not be called outside the class! | |
''' | |
return str1.find(substr1, str1.find(substr1)+1) | |
# This will only avoid a string with numbers | |
def __validate_name(self, name): | |
'''Internal function that check the entered name. | |
This should return True if the string entered | |
has a valid format, and should return false | |
if it contains invalid character. | |
This method should not be called outside the class! | |
''' | |
if re.search("\d", name) == None: | |
# No digit is inside the string 'name' | |
return True | |
else: | |
return False | |
def __validate_email(self, email): | |
'''Internal function that check the entered email. | |
This should return True if the string entered has a valid format. | |
Example of a valid format: '[email protected]' where X>1 & Y>1 | |
This method should not be called outside the class! | |
''' | |
try: | |
atpos = email.index('@') | |
# Get the position of the first '.' after '@' | |
dotpos = email.find('.', email.find('@')) | |
top = len(email) | |
if (top<128)&(email.count('@')==1)&(atpos >= 1)&(dotpos == top-4): | |
return True | |
else: | |
# string 'email' has a invalid format | |
return False | |
except ValueError: | |
# Reached if no at character ('@') was found | |
return False |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment