Jump to content

Very first workflow (python)


Recommended Posts

Hi all,

 

I'm trying to get my first workflow ever up and running. Its a modification of Jeremy Pippin's password generator, but this one has a larger dictionary, random word selection from random.org's API, and a parameter for the number of words you want.

Right now nothing happens when I run it using Alfred with no {query}. I'm sure its something simple - I'm not sure that I'm checking for the existence of {query} properly.
 

The python script is below. I have the workflow set up to copy the output to the clipboard and paste into the frontmost app.
"zoe",
"zomba",
"zone",
"zoo",
"zoom",
"zorn",
"zurich",
 ]

import urllib2

def generate_password(length = 5):
	maximum = len(wordList)
	i = 0
	password = []
	while i < length:
		random_request = "http://www.random.org/integers/?num=1&min=0&max=" + str(maximum) + "&col=1&base=10&format=plain&rnd=new"
		random_page = urllib2.urlopen(random_request)
		random_integer = int(random_page.read().rstrip('\n'))
		new_word = wordList[random_integer]
		password.append(new_word)
		i = i + 1

	number_request = "http://www.random.org/integers/?num=1&min=0&max=99&col=1&base=10&format=plain&rnd=new"
	number_page = urllib2.urlopen(number_request)
	number_integer = number_page.read().rstrip('\n')
	password.append(number_integer)
	
	password = '-'.join(password)
	return(password)

query = {query}
if 'query' in globals():
	print(generate_password(query))
else:
	print(generate_password())

Thanks for helpin' out a noobie!

Edited by justmytwospence
Link to comment

I've figured out a way to make it work with a try/except. Can anyone confirm that it is the simplest/best way?

#!/usr/bin/env python 

import urllib2
import sys

f = open('wordlist.csv', 'r')
wordlist = f.readlines()
for x in range(0,len(wordlist)):
	wordlist[x] = wordlist[x].rstrip(',\n')

def generate_password(length = 4):
	maximum = len(wordlist)
	random_request = "http://www.random.org/integers/?num=" + str(length + 1) + "&min=0&max=" + str(maximum) + "&col=1&base=10&format=plain&rnd=new"
	random_page = urllib2.urlopen(random_request)
	random_integers = random_page.readlines()

	for x in range(0, length):
		random_integers[x] = int(random_integers[x].rstrip('\n'))

	i = 0
	password = []
	while i < length:
		new_word = wordlist[random_integers[i]]
		password.append(new_word)
		i = i + 1

	password.append(random_integers[i][:2])
	
	password = '-'.join(password)
	return(password)

try:
	query = int(sys.argv[1])
	print(generate_password(query))
except:
	print(generate_password())
Edited by justmytwospence
Link to comment

 

I've figured out a way to make it work with a try/except. Can anyone confirm that it is the simplest/best way?

#!/usr/bin/env python 

import urllib2
import sys

f = open('wordlist.csv', 'r')
wordlist = f.readlines()
for x in range(0,len(wordlist)):
	wordlist[x] = wordlist[x].rstrip(',\n')

def generate_password(length = 4):
	maximum = len(wordlist)
	random_request = "http://www.random.org/integers/?num=" + str(length + 1) + "&min=0&max=" + str(maximum) + "&col=1&base=10&format=plain&rnd=new"
	random_page = urllib2.urlopen(random_request)
	random_integers = random_page.readlines()

	for x in range(0, length):
		random_integers[x] = int(random_integers[x].rstrip('\n'))

	i = 0
	password = []
	while i < length:
		new_word = wordlist[random_integers[i]]
		password.append(new_word)
		i = i + 1

	password.append(random_integers[i][:2])
	
	password = '-'.join(password)
	return(password)

try:
	query = int(sys.argv[1])
	print(generate_password(query))
except:
	print(generate_password())

 

What is it doing/not doing? Does the script run normally by itself? Where is wordlist.csv located? In the workflow folder? Workflows path is relative to the workflow folder

Link to comment

wordlist.csv is indeed in the workflow folder. Its actually up and running now - but I'm still not sure the way I am passing parameters to the python script is the best way. Right now, the workflow runs this command using bash:

./randomGen.py {query}

I can pass it two arguments from Alfred this way, which are interpreted as argv[1] and argv[2] by the python sys module. I am jerry-rigging default parameters using try/except, which is functional but seems clunky. Additionally, it means that I can't give the second Alfred argument unless I also give the first (otherwise it will be argv[1] instead of argv[2]).

 

#!/usr/bin/env python 

import urllib2
import sys

try:
	dictionary = str(sys.argv[2]).lower() + '.txt'
except:
	dictionary = 'british.txt'

with open(dictionary, 'r') as handle:
	wordlist = handle.readlines()
	for x in range(0,len(wordlist)):
		wordlist[x] = wordlist[x].strip()

def generate_password(length = 4):
	maximum = len(wordlist)
	random_request = "http://www.random.org/integers/?num=" + str(length + 1) + "&min=0&max=" + str(maximum) + "&col=1&base=10&format=plain&rnd=new"
	random_page = urllib2.urlopen(random_request)
	random_integers = random_page.readlines()

	for x in range(0, length):
		random_integers[x] = int(random_integers[x].rstrip('\n'))

	i = 0
	password = []
	while i < length:
		new_word = wordlist[random_integers[i]]
		password.append(new_word)
		i = i + 1

	password.append(random_integers[i][:2])
	
	password = '-'.join(password)
	return(password)

try:
	query = int(sys.argv[1])
	print(generate_password(query))
except:
	print(generate_password())

How do y'all who use python with Alfred deal with parameters?

Link to comment

wordlist.csv is indeed in the workflow folder. Its actually up and running now - but I'm still not sure the way I am passing parameters to the python script is the best way. Right now, the workflow runs this command using bash:

./randomGen.py {query}

I can pass it two arguments from Alfred this way, which are interpreted as argv[1] and argv[2] by the python sys module. I am jerry-rigging default parameters using try/except, which is functional but seems clunky. Additionally, it means that I can't give the second Alfred argument unless I also give the first (otherwise it will be argv[1] instead of argv[2]).

 

#!/usr/bin/env python 

import urllib2
import sys

try:
	dictionary = str(sys.argv[2]).lower() + '.txt'
except:
	dictionary = 'british.txt'

with open(dictionary, 'r') as handle:
	wordlist = handle.readlines()
	for x in range(0,len(wordlist)):
		wordlist[x] = wordlist[x].strip()

def generate_password(length = 4):
	maximum = len(wordlist)
	random_request = "http://www.random.org/integers/?num=" + str(length + 1) + "&min=0&max=" + str(maximum) + "&col=1&base=10&format=plain&rnd=new"
	random_page = urllib2.urlopen(random_request)
	random_integers = random_page.readlines()

	for x in range(0, length):
		random_integers[x] = int(random_integers[x].rstrip('\n'))

	i = 0
	password = []
	while i < length:
		new_word = wordlist[random_integers[i]]
		password.append(new_word)
		i = i + 1

	password.append(random_integers[i][:2])
	
	password = '-'.join(password)
	return(password)

try:
	query = int(sys.argv[1])
	print(generate_password(query))
except:
	print(generate_password())

How do y'all who use python with Alfred deal with parameters?

 

Well, there are several ways to do this. You could just copy and paste your code directly into the Alfred Run Script area. Then you could set the value of a variable to {query}. The {query} placeholder is used to pass input into a workflow item. If you need multiple words, you could still pass the entire input string and just use the .split() function in python to split on a space and return an array of all words.

Link to comment

wordlist.csv is indeed in the workflow folder. Its actually up and running now - but I'm still not sure the way I am passing parameters to the python script is the best way. Right now, the workflow runs this command using bash:

./randomGen.py {query}

I can pass it two arguments from Alfred this way, which are interpreted as argv[1] and argv[2] by the python sys module. I am jerry-rigging default parameters using try/except, which is functional but seems clunky. Additionally, it means that I can't give the second Alfred argument unless I also give the first (otherwise it will be argv[1] instead of argv[2]).

 

#!/usr/bin/env python 

import urllib2
import sys

try:
	dictionary = str(sys.argv[2]).lower() + '.txt'
except:
	dictionary = 'british.txt'

with open(dictionary, 'r') as handle:
	wordlist = handle.readlines()
	for x in range(0,len(wordlist)):
		wordlist[x] = wordlist[x].strip()

def generate_password(length = 4):
	maximum = len(wordlist)
	random_request = "http://www.random.org/integers/?num=" + str(length + 1) + "&min=0&max=" + str(maximum) + "&col=1&base=10&format=plain&rnd=new"
	random_page = urllib2.urlopen(random_request)
	random_integers = random_page.readlines()

	for x in range(0, length):
		random_integers[x] = int(random_integers[x].rstrip('\n'))

	i = 0
	password = []
	while i < length:
		new_word = wordlist[random_integers[i]]
		password.append(new_word)
		i = i + 1

	password.append(random_integers[i][:2])
	
	password = '-'.join(password)
	return(password)

try:
	query = int(sys.argv[1])
	print(generate_password(query))
except:
	print(generate_password())

How do y'all who use python with Alfred deal with parameters?

 

Generally speaking, I think it's best to do a series of conditional checks for the length of argv. So your code could be rewritten to look something like this:

import urllib2
import sys

args = sys.argv

def generate_password(length = 4, dictionary = "british"):
    dict_file = dictionary.lower() + ".txt"
    with open(dict_file) as f:
        orig_list = f.readlines()
        wordlist = []
        for word in orig_list:
            wordlist.append(word.strip())

    maximum = len(wordlist)
    # etc.
    return password

if len(args) == 1: #sys.argv[0] is always your script's name
    print generate_password()
if len(args) == 2:
    query = int(args[1])
    print generate_password(length=query)
if len(args) == 3:
    query = int(args[1])
    dictionary = str(args[2])
    print generate_password(length=query, dictionary=dictionary)

Because—at least according to my quick experimenting—all the objects in sys.argv are type str, even if they can be cast to or treated as numbers, it'd be hard to test for whether the user entered just a dictionary name. You could do it by not adding .txt automatically, and then checking to see if .txt was in the argument's string:

import sys


args = sys.argv

if len(args) == 2 and ".txt" in args[1]:
    print generate_password(dictionary=args[1])
elif len(args) == 2:
    print generate_password(length=args[1])
elif len(args) == 3:
    # etc.
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...