Move shelve handling to class level – Instead of opening/closing the shelve all the time, I would suggest to let it follow the lifetime of the class, and add a
sync
method to the class. This would reduce the file operations, and you can keep the shelve open within the class.This would allow for all of the read access to be almost instant as the file is already read into memory (and the encrypted password should still be encrypted). And when doing changing password methods, you could trigger a sync, writing the shelve back to the file.
Two links which might be helpful in doing this:
- Persistent dict with multiple standard file formats (Python recipe – Which provides some structural stuff related to you use of shelve
- Safely using destructors in Python – Related to handling lifetime opening and closing of the shelve (in a slightly different context)
A better class name –
main
is a terrible name, you should choose a better name likePasswordHandler
orAccountHandler
. As already suggested I would move the shelve handling to the outer level, and possibly add a few class methods. I.e. a static class method to verify if a user has entered the correct password would be nice to have.Allow methods not to use input – To improve the interface, I would change the methods allowing input to accept that input to be predefined as a parameter. I'll show some code for one of the functions which could accomplish this:
def change_password(self, account, username, new_password=None, log=True): if not new_password: new_password = input('Enter new password: \n ->')
def change_password(self, account, username, new_password=None, log=True): if not new_password: new_password = input('Enter new password: \n ->') with shelve.open(self.File) as f: f[account][username][2] = self.EC.encrypt(new_password) if log: entry = f[account][username] print(self.template.format(entry[0], entry[1], new_password))
This still uses the old code for the shelve handling, but you'll get the gist of the idea.
Let methods return list, not do the actual output – Instead of letting your methods, like
all_users
, do the print, in general it's better to let the method returning the list of users for extra handling, i.e. printing or sorting before printing or whatever...Move class level code into
__init__
– Doing stuff likekey = input(...)
is very strange, and should be moved into a method of it's own, namely the__init__
, which is automatically called whenever you create an instance of your class.
Move shelve handling to class level – Instead of opening/closing the shelve all the time, I would suggest to let it follow the lifetime of the class, and add a
sync
method to the class. This would reduce the file operations, and you can keep the shelve open within the class.This would allow for all of the read access to be almost instant as the file is already read into memory (and the encrypted password should still be encrypted). And when doing changing password methods, you could trigger a sync, writing the shelve back to the file.
Two links which might be helpful in doing this:
- Persistent dict with multiple standard file formats (Python recipe – Which provides some structural stuff related to you use of shelve
- Safely using destructors in Python – Related to handling lifetime opening and closing of the shelve (in a slightly different context)
A better class name –
main
is a terrible name, you should choose a better name likePasswordHandler
orAccountHandler
. As already suggested I would move the shelve handling to the outer level, and possibly add a few class methods. I.e. a static class method to verify if a user has entered the correct password would be nice to have.Allow methods not to use input – To improve the interface, I would change the methods allowing input to accept that input to be predefined as a parameter. I'll show some code for one of the functions which could accomplish this:
def change_password(self, account, username, new_password=None, log=True): if not new_password: new_password = input('Enter new password: \n ->')
with shelve.open(self.File) as f: f[account][username][2] = self.EC.encrypt(new_password) if log: entry = f[account][username] print(self.template.format(entry[0], entry[1], new_password))
This still uses the old code for the shelve handling, but you'll get the gist of the idea.
Let methods return list, not do the actual output – Instead of letting your methods, like
all_users
, do the print, in general it's better to let the method returning the list of users for extra handling, i.e. printing or sorting before printing or whatever...Move class level code into
__init__
– Doing stuff likekey = input(...)
is very strange, and should be moved into a method of it's own, namely the__init__
, which is automatically called whenever you create an instance of your class.
Move shelve handling to class level – Instead of opening/closing the shelve all the time, I would suggest to let it follow the lifetime of the class, and add a
sync
method to the class. This would reduce the file operations, and you can keep the shelve open within the class.This would allow for all of the read access to be almost instant as the file is already read into memory (and the encrypted password should still be encrypted). And when doing changing password methods, you could trigger a sync, writing the shelve back to the file.
Two links which might be helpful in doing this:
- Persistent dict with multiple standard file formats (Python recipe – Which provides some structural stuff related to you use of shelve
- Safely using destructors in Python – Related to handling lifetime opening and closing of the shelve (in a slightly different context)
A better class name –
main
is a terrible name, you should choose a better name likePasswordHandler
orAccountHandler
. As already suggested I would move the shelve handling to the outer level, and possibly add a few class methods. I.e. a static class method to verify if a user has entered the correct password would be nice to have.Allow methods not to use input – To improve the interface, I would change the methods allowing input to accept that input to be predefined as a parameter. I'll show some code for one of the functions which could accomplish this:
def change_password(self, account, username, new_password=None, log=True): if not new_password: new_password = input('Enter new password: \n ->') with shelve.open(self.File) as f: f[account][username][2] = self.EC.encrypt(new_password) if log: entry = f[account][username] print(self.template.format(entry[0], entry[1], new_password))
This still uses the old code for the shelve handling, but you'll get the gist of the idea.
Let methods return list, not do the actual output – Instead of letting your methods, like
all_users
, do the print, in general it's better to let the method returning the list of users for extra handling, i.e. printing or sorting before printing or whatever...Move class level code into
__init__
– Doing stuff likekey = input(...)
is very strange, and should be moved into a method of it's own, namely the__init__
, which is automatically called whenever you create an instance of your class.
I've seen your question and would like to give you a full review, but haven't had the time yet. So now I decided to give you some of the recommendations, and then we'll see if I get the time to complete it or add to it later on.
Move shelve handling to class level – Instead of opening/closing the shelve all the time, I would suggest to let it follow the lifetime of the class, and add a
sync
method to the class. This would reduce the file operations, and you can keep the shelve open within the class.This would allow for all of the read access to be almost instant as the file is already read into memory (and the encrypted password should still be encrypted). And when doing changing password methods, you could trigger a sync, writing the shelve back to the file.
Two links which might be helpful in doing this:
- Persistent dict with multiple standard file formats (Python recipe – Which provides some structural stuff related to you use of shelve
- Safely using destructors in Python – Related to handling lifetime opening and closing of the shelve (in a slightly different context)
A better class name –
main
is a terrible name, you should choose a better name likePasswordHandler
orAccountHandler
. As already suggested I would move the shelve handling to the outer level, and possibly add a few class methods. I.e. a static class method to verify if a user has entered the correct password would be nice to have.Allow methods not to use input – To improve the interface, I would change the methods allowing input to accept that input to be predefined as a parameter. I'll show some code for one of the functions which could accomplish this:
def change_password(self, account, username, new_password=None, log=True): if not new_password: new_password = input('Enter new password: \n ->')
with shelve.open(self.File) as f: f[account][username][2] = self.EC.encrypt(new_password) if log: entry = f[account][username] print(self.template.format(entry[0], entry[1], new_password))
This still uses the old code for the shelve handling, but you'll get the gist of the idea.
Let methods return list, not do the actual output – Instead of letting your methods, like
all_users
, do the print, in general it's better to let the method returning the list of users for extra handling, i.e. printing or sorting before printing or whatever...Move class level code into
__init__
– Doing stuff likekey = input(...)
is very strange, and should be moved into a method of it's own, namely the__init__
, which is automatically called whenever you create an instance of your class.
There are some other minor aspects still not covered (neither in mine, nor the other answer which just came in), but these matters are some of the main issues I see in your code.