20
\$\begingroup\$

In preparation for the end of Code Review's 2015 election, I've built a simple bot to get the election votes, run OpenSTV on them, and post the result to a chatroom. I'm using this Python implementation of STV and ManishEarth's ChatExchange.

import getpass
import logging
import os
import time
import urllib
import sys
from subprocess import call

import ChatExchange.chatexchange
from ChatExchange.chatexchange.events import MessageEdited

logging.captureWarnings(True)

class bcolors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'

logging.basicConfig(level=logging.CRITICAL)

if 'ChatExchangeU' in os.environ:
    email = os.environ['ChatExchangeU']
else:
    email = raw_input("Email: ")
if 'ChatExchangeP' in os.environ:
    password = os.environ['ChatExchangeP']
else:
    password = getpass.getpass("Password: ")
client = ChatExchange.chatexchange.Client('stackexchange.com', email, password)

raw_input(bcolors.BOLD + bcolors.OKGREEN + "Connection good." + bcolors.ENDC + bcolors.BOLD + " [Enter] to proceed getting results for " + sys.argv[1] + " election #" + sys.argv[2] + "..." + bcolors.ENDC)

urllib.urlretrieve ("http://" + sys.argv[1] + "/election/download-result/" + sys.argv[2], "votes.blt")

result = os.popen("python runElection.py MeekSTV votes.blt").read()

os.remove("votes.blt")

result_indented = ""

for string in result.splitlines():
    result_indented = result_indented + "    " + string + "\n"

print result_indented

winners_line = ">" + result_indented.splitlines()[-1]

okay_to_post = raw_input("Okay to post? ")
if okay_to_post.lower() == "y":
    sandbox = client.get_room(sys.argv[3])
    sandbox.send_message(winners_line)
    sandbox.send_message(result_indented, False)

    time.sleep(40)

I run it from the command line like so:

python StackElectChat.py <site> <election number> <chatroom id>

For example, running this:

python StackElectChat.py serverfault.com 2 17251

Would take the results from Server Fault's second election and post it to Chatroom #17251.

Some concerns:

  • I don't like how I'm doing colors for it (taken from this Stack Overflow answer), is there a built in way?
  • okay_to_post.lower() seems like a hack - is there a built in way to check for an affirmative answer to a request?
  • I don't like how I iterate over every line to add code formatting (four spaces) to the chat message
\$\endgroup\$

2 Answers 2

11
\$\begingroup\$

To address your first concern, the way you're doing colors is fine... If you're not running Windows. If you try to use raw ANSI codes like this on windows, you're going to run into some issues. Personally, I'd recommend using the Colorama. It's pretty easy to use. For example, if I wanted to print yellow text with a red background, I'd do this:

from colorama import init, Fore, Back

init()

print(Fore.YELLOW + Back.RED + "Text!")

Secondly, using str.lower on input, isn't really all that hacky, and it's done quite a lot when obtaining user input. In short, it's okay.

Finally, I'm noticing that you're using string concatenation to display variables in a string. The proper way to do this would be to use str.format. Here's how that'd be done:

# Normal str.format without positional or
# named parameters.
print "{} {}".format("Hello", "world")

# str.format with positional parameters (*args)
print "{1} {0}".format("world", "Hello")

# str.format with named parameters (**kwargs)
print "{word1} {word2}".format(word1="Hello", word2="world")
\$\endgroup\$
10
\$\begingroup\$

You're right to be suspicious about this part:

result_indented = ""

for string in result.splitlines():
    result_indented = result_indented + "    " + string + "\n"

print result_indented

winners_line = ">" + result_indented.splitlines()[-1]

The Pythonic way to build result_indented would be using a list comprehension. But a bigger problem here is the wasteful splitlines twice. A better way to write this:

result_indented = ['    {}\n'.format(x) for x in result.splitlines()]
print(''.join(result_indented))

winners_line = '> ' + result_indented[-1]
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.