Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Mar 2nd, 2006, 10:07 PM   #1
Jessehk
The Oblivious One
 
Jessehk's Avatar
 
Join Date: May 2005
Location: Ontario, Canada
Posts: 648
Rep Power: 4 Jessehk is on a distinguished road
Defining and handling command-line options

I made a password-generator in Python.
I figure that it would be much faster if it could be called like this

Quote:

password <length> [options]
I was just wondering if I handled these arguments appropriately, and if I didn't, how the program could be improved.

#!/usr/bin/python

import random, sys

class Password:
	lower_letters = [letter for letter in 'abcdefghijklmnopqrstuvwxyz']
	upper_letters = [letter for letter in 'ABCDEFGHIJKLMNOPQRSTUVWXWZ']
	numbers = [str(x) for x in range(10)]
	symbols = [s for s in '\/<>!@#$%^&*']

	def __init__(self, length, lower, upper, symbol, number):
		if length < 0:
			raise ValueError("Invalid length of password.")
		
		else:
			possible = []
			if lower:
				possible.extend(self.lower_letters) #include lower-case letters
			if upper:
				possible.extend(self.upper_letters) #include upper-case letters
			if symbol:
				possible.extend(self.symbols) #include symbols
			if number:
				possible.extend(self.numbers) #include [0 - 9]

			self.password = []
			
			for x in range(length):
				self.password.append(random.choice(possible))
		
	def get_password(self):
		return "".join(self.password) #string version of password

def main():
	lower = upper = number = symbol = False

	error = """Invalid usage

	password <length> [options]

	options
	-------
	
	-l : include lower-case letters in the password
	-u : include upper-case letters in the password
	-s : include symbols in the password
	-n : include the digits 0 - 9 in the password
	-* : include everything in the password
	"""
	
	try:
		if len(sys.argv) < 2:
			raise ValueError(error)

		if "-*" in sys.argv:
			lower = upper = number = symbol = True
		
		else:
			if "-l" in sys.argv:
				lower = True
			if "-u" in sys.argv:
				upper = True
			if "-n" in sys.argv:
				number = True
			if "-s" in sys.argv:
				symbol = True
		
			
		if not True in (lower, upper, number, symbol):
			raise ValueError(error)

		p = Password(int(sys.argv[1]), lower, upper, symbol, number)
		print p.get_password()
	
	except ValueError, ve:
		print error

if __name__ == '__main__':
	main()
__________________
Dr. Zoidberg: [ecstatic] I'm going to a movie... with FRIENDS!

Last edited by Jessehk; Mar 2nd, 2006 at 10:07 PM. Reason: Forgot code tags for some reason...
Jessehk is offline   Reply With Quote
Old Mar 2nd, 2006, 10:21 PM   #2
hydroxide
Programmer
 
Join Date: Apr 2005
Posts: 73
Rep Power: 4 hydroxide is on a distinguished road
Use the optparse module - you'll end up with shorter, more robust, and more extensible code.

-T.
hydroxide is offline   Reply With Quote
Old Mar 2nd, 2006, 10:41 PM   #3
Sane
Banned
 
Sane's Avatar
 
Join Date: Apr 2005
Location: Waterloo, Ontario
Posts: 2,101
Rep Power: 6 Sane will become famous soon enough
Send a message via MSN to Sane
Just a note, I prefer doing stuff like:
	lower_letters = [letter for letter in 'abcdefghijklmnopqrstuvwxyz']
	upper_letters = [letter for letter in 'ABCDEFGHIJKLMNOPQRSTUVWXWZ']
In a shorter fasion such as:
        lower_letters = [chr(letter) for letter in range(97, 123)]
        upper_letters = [chr(letter) for letter in range(65, 91)]
Just a personal preference though.
Sane is offline   Reply With Quote
Old Mar 2nd, 2006, 11:06 PM   #4
Jessehk
The Oblivious One
 
Jessehk's Avatar
 
Join Date: May 2005
Location: Ontario, Canada
Posts: 648
Rep Power: 4 Jessehk is on a distinguished road
New Version:

#!/usr/bin/python

import random, sys
from optparse import OptionParser

class Password:
	lower_letters = [letter for letter in 'abcdefghijklmnopqrstuvwxyz']
	upper_letters = [letter for letter in 'ABCDEFGHIJKLMNOPQRSTUVWXWZ']
	numbers = [str(x) for x in range(10)]
	symbols = [s for s in '\/<>!@#$%^&*']

	def __init__(self, length, lower, upper, symbol, number):
		if length < 0:
			raise ValueError("Invalid length of password.")
		
		else:
			possible = []
			if lower:
				possible.extend(self.lower_letters) #include lower-case letters
			if upper:
				possible.extend(self.upper_letters) #include upper-case letters
			if symbol:
				possible.extend(self.symbols) #include symbols
			if number:
				possible.extend(self.numbers) #include [0 - 9]

			self.password = []
			
			for x in range(length):
				self.password.append(random.choice(possible))
		
	def get_password(self):
		return "".join(self.password) #string version of password

def main():
	parser = OptionParser(usage = "usage: %prog [options] length")
	parser.add_option("-l", action = "store_true", default = True, dest = "lower", help = "include lower-case letters (default)")
	parser.add_option("-u", action = "store_true", default = False, dest = "upper", help = "include upper-case letters")
	parser.add_option("-n", action = "store_true", default = False, dest = "number", help = "include the digits from 0 to 9")
	parser.add_option("-s", action = "store_true", default = False, dest = "symbol", help = "include symbols (eg: $%^\/!)")

	(options, args) = parser.parse_args()
	if len(args) != 1:
		parser.error("Incorrect number of arguments")

	try:
		p = Password(int(args[0]), options.lower, options.upper, options.number, options.symbol)

	except ValueError, ve:
		parser.print_help()
	
	else:
		print p.get_password()

if __name__ == '__main__':
	main()

Thanks for info, OH!

@Sane: I appreciate the advice, but I think my method is a bit more readable (ie: the intention is clearly obvious).
__________________
Dr. Zoidberg: [ecstatic] I'm going to a movie... with FRIENDS!
Jessehk is offline   Reply With Quote
Old Mar 3rd, 2006, 2:49 AM   #5
Arevos
Programming Guru
 
Arevos's Avatar
 
Join Date: Aug 2005
Location: England
Posts: 1,499
Rep Power: 5 Arevos is on a distinguished road
Quote:
Originally Posted by Sane
In a shorter fasion such as:
        lower_letters = [chr(letter) for letter in range(97, 123)]
        upper_letters = [chr(letter) for letter in range(65, 91)]
Just a personal preference though.
Or, use the string module:
lower_letters = list(string.ascii_lowercase)
upper_letters = list(string.ascii_uppercase)
numbers = list(string.digits)
symbols = list("\/<>!@#$%^&*")
Arevos is offline   Reply With Quote
Old Mar 3rd, 2006, 8:29 PM   #6
Cerulean
Professional Programmer
 
Cerulean's Avatar
 
Join Date: Apr 2005
Location: London, England
Posts: 459
Rep Power: 4 Cerulean is on a distinguished road
Yeah, things like [x for x in "some string"] are redundant as list("some string") does the same. I would imagine the latter is faster too.
I don't know about using the string module really. You type less for digits without the module (i.e len("'0123456789'") < len("string.digits")), and just a little more for upper case and lower case characters. I only use it for string.punctuation
Cerulean is offline   Reply With Quote
Old Mar 3rd, 2006, 11:30 PM   #7
Jessehk
The Oblivious One
 
Jessehk's Avatar
 
Join Date: May 2005
Location: Ontario, Canada
Posts: 648
Rep Power: 4 Jessehk is on a distinguished road
Somehow, list(string) was absent from my mind. I'll remember for the future I suppose.
__________________
Dr. Zoidberg: [ecstatic] I'm going to a movie... with FRIENDS!
Jessehk is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 12:27 PM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC