#!/usr/bin/env python
from __future__ import print_function
import string
import random
import argparse
import sys


def passgen(length=12, punctuation=False, digits=True, letters=True,
            case="both"):
    """Generate a random password with *length* characters"""
    if length < 1:
        raise ValueError("length must be greater than zero")
    pool = []
    if letters:
        if case == "both":
            pool.append(string.ascii_uppercase + string.ascii_lowercase)
        elif case == "upper":
            pool.append(string.ascii_uppercase)
        elif case == "lower":
            pool.append(string.ascii_lowercase)
        else:
            raise ValueError("case can only be 'both', 'upper' or 'lower'")
    if digits:
        pool.append(string.digits)
    if punctuation:
        pool.append(string.punctuation)
    pool = "".join(pool)

    # Using technique from Stack Overflow answer
    # http://stackoverflow.com/a/23728630
    chars = [random.SystemRandom().choice(pool) for _ in range(length)]
    return "".join(chars)


def _error(msg=""):
    print("passgen: error: " + msg, file=sys.stderr)
    sys.exit(1)


def main():
    parser = argparse.ArgumentParser(
        description="Generate strong random password."
    )
    parser.add_argument("-l", "--length",
                        help="the number of characters to generate "
                             "for each password",
                        type=int, default=12)
    parser.add_argument("-n", "--number",
                        help="how many passwords to generate",
                        type=int, default=10)
    parser.add_argument("-p", "--punctuation",
                        help="use punctuation characters",
                        action='store_true')
    parser.add_argument("--no-digits",
                        help="don't include digits",
                        action='store_false', dest='digits')
    parser.add_argument("--no-letters",
                        help="don't include letters",
                        action='store_false', dest='letters')
    case_group = parser.add_mutually_exclusive_group()
    case_group.add_argument("--upper",
                            help="use only upper case letters",
                            action='store_true')
    case_group.add_argument("--lower",
                            help="use only lower case letters",
                            action='store_true')
    args = parser.parse_args()
    print(args)

    if args.length < 1:
        _error("argument -l/--length must be greater than zero")
    if args.number < 1:
        _error("argument -n/--number must be greater than zero")

    if args.lower:
        case = "lower"
    elif args.upper:
        case = "upper"
    else:
        case = "both"

    for _ in range(args.number):
        print(passgen(args.length, punctuation=args.punctuation,
                      digits=args.digits,
                      letters=args.letters, case=case))

@@ -1225,15 +1225,8 @@
 ate 
-strong 
 rand
@@ -1239,16 +1239,16 @@
 sword.%22%0A
+
     )%0A  
@@ -1325,31 +1325,21 @@
 the 
-number of characters to
+length of the
  gen
@@ -1343,16 +1343,17 @@
 generate
+d
  %22%0A     
@@ -1381,25 +1381,30 @@
    %22
-for each password
+password (default: 12)
 %22,%0A 
@@ -1550,16 +1550,30 @@
 generate
+ (default: 10)
 %22,%0A     
@@ -1839,22 +1839,18 @@
 =%22don't 
-includ
+us
 e digits
@@ -1993,14 +1993,10 @@
 n't 
-includ
+us
 e le

Update argparse descriptions