import sys
from os.path import expanduser
import mechanize
from bug import Bug, BugNotFound
import textwrap
import argparse
import pydoc
from ConfigParser import SafeConfigParser, NoSectionError

class NoPaging(Exception): pass
def windowsize():
	from fcntl import ioctl
	from termios import TIOCGWINSZ
	from array import array
	winsize = array("H", [0, 0, 0, 0] )
	ioctl(sys.stdout.fileno(), TIOCGWINSZ, winsize)
	return (winsize[1], winsize[0])

class Bugger(object):
	def __init__(self, url):
		self.url = url
		self.browser = mechanize.Browser()

	def bug(self, bug_id):
		response = self.browser.open("%s/view.php?id=%d" % ( self.url, bug_id))
		return Bug(response.read())

def main_func():
	reload(sys)
	sys.setdefaultencoding("utf-8")
	configparser = SafeConfigParser()
	url = None
	for p in ['.buggerrc', expanduser('~/.buggerrc'), expanduser('~/.config/bugger/buggerrc')]:
		try:
			configparser.readfp(open(p))
			break #success, break
		except IOError: #no such config file?
			pass

	parser = argparse.ArgumentParser(description='Mechanized Mantis', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
	try:
		parser.set_defaults(**dict(configparser.items('bugger')))
	except NoSectionError:
		fallback_defaults = {
				'url': 'http://tracker.example.com',
				}
		parser.set_defaults(**fallback_defaults)
	parser.add_argument('--url', '-u', help='URL to Mantis')
	parser.add_argument('--template', '-t', help='Path to rendering template for bugs')
	parser.add_argument('id', type=int, help='ID of the bug to operate on')
	args = parser.parse_args()
	url = args.url
	bug_id = args.id
	output = ""
	try:
		bug = Bugger(url).bug(bug_id)
		output = bug.render(args.template)
	except BugNotFound:
		output = "Sorry, that bug doesn't exist."

	try:
		width, height = windowsize()
		if output.count("\n") > height:
			pydoc.pager(output)
		else:
			raise NoPaging
	except (IOError, NoPaging):
		print(output)
		pass


if __name__ == '__main__':
	main_func()

@@ -42,25 +42,65 @@
 %0Aimport 
-mechanize
+re%0Aimport mechanize%0Afrom bs4 import BeautifulSoup
 %0Afrom bu
@@ -261,16 +261,57 @@
 ): pass%0A
+class BuggerLoginError(Exception): pass%0A%0A
 def wind
@@ -549,85 +549,822 @@
 ):%0A%09
-def __init__(self, url):%0A%09%09self.url = url%0A%09%09self.browser = mechanize.Browser(
+texts = %7B%22access_denied%22: re.compile(%22Your account may be disabled or blocked or the username/password you entered is incorrect.%22)%7D%0A%09def __init__(self, url):%0A%09%09self.url = url%0A%09%09self.browser = mechanize.Browser()%0A%09%09self.browser.set_handle_refresh(mechanize._http.HTTPRefreshProcessor(), max_time=1)%0A%0A%09def login(self, username, password):%0A%09%09self.browser.open(%22%25s/login_page.php%22 %25 self.url)%0A%09%09self.browser.select_form(%22login_form%22)%0A%09%09self.browser.method = %22POST%22%0A%09%09username_control = self.browser.find_control(%22username%22)%0A%09%09password_control = self.browser.find_control(%22password%22)%0A%09%09username_control.value = username%0A%09%09password_control.value = password%0A%09%09soup = BeautifulSoup(self.browser.submit())%0A%09%09if soup.find(%22div%22, text=self.texts%5B%22access_denied%22%5D):%0A%09%09%09raise BuggerLoginError(%22Login failed for '%25s'%22 %25 username
 )%0A%0A%09

add login method