[SM-Commit] GIT changes to master grimoire by Andraž Levstik (7e1f4acd3e18933b5ff21f0ef44775bbe4794a5b)

Andraž Levstik scm at sourcemage.org
Sun Oct 10 14:52:43 EDT 2010


GIT changes to master grimoire by Andraž Levstik <ruskie+2054d253 at codemages.net>:

 python-pypi/pybugz/HISTORY                   |    4 
 python-pypi/pybugz/PRE_BUILD                 |    1 
 python-pypi/pybugz/all_current_updates.patch |  838 +++++++++++++++++++++++++++
 3 files changed, 842 insertions(+), 1 deletion(-)

New commits:
commit aa54aa63a24f6cc86bb4b3baf4665a158692ce3c
Author: Andraž Levstik <ruskie+2054d253 at codemages.net>
Commit: Andraž Levstik <ruskie+2054d253 at codemages.net>

    pybugz: added patch to bring it up to date

diff --git a/python-pypi/pybugz/HISTORY b/python-pypi/pybugz/HISTORY
index d01cc46..9f0fac8 100644
--- a/python-pypi/pybugz/HISTORY
+++ b/python-pypi/pybugz/HISTORY
@@ -1,7 +1,9 @@
 2010-10-10 Andraž "ruskie" Levstik <ruskie+f03a580f at codemages.net>
 	* DETAILS: Fixed SOURCE_URL[0]
 	  updated spell to 0.8.0
-	* PRE_BUILD: made it friendly for our bugzilla
+	* PRE_BUILD: made it friendly for our bugzilla, added patch for fixes(python
+	  2.7)
+	* all_current_updates.patch: patch to bring it up to date with the git stuff
 
 2009-08-05 George Sherwood <gsherwood at sourcemage.org>
 	* DETAILS, DEPENDS, PRE_BUILD, python-2.6-elementtree.patch:
diff --git a/python-pypi/pybugz/PRE_BUILD b/python-pypi/pybugz/PRE_BUILD
index 81b4bef..2ce7cc8 100755
--- a/python-pypi/pybugz/PRE_BUILD
+++ b/python-pypi/pybugz/PRE_BUILD
@@ -1,4 +1,5 @@
 default_pre_build &&
 cd $SOURCE_DIRECTORY &&
+patch -p1 < $SPELL_DIRECTORY/all_current_updates.patch &&
 # make it friendly for our bugzilla
 sed -i -e "s/https:\/\/bugs.gentoo.org/http:\/\/bugs.sourcemage.org/" bugz/cli.py
diff --git a/python-pypi/pybugz/all_current_updates.patch b/python-pypi/pybugz/all_current_updates.patch
new file mode 100644
index 0000000..b7b54ca
--- /dev/null
+++ b/python-pypi/pybugz/all_current_updates.patch
@@ -0,0 +1,838 @@
+diff --git a/bin/bugz b/bin/bugz
+index 39229ac..afaa4f8 100755
+--- a/bin/bugz
++++ b/bin/bugz
+@@ -4,79 +4,28 @@ import locale
+ import sys
+ import traceback
+ 
+-from optparse import OptionParser
+-
+-from bugz import cli, __version__
+ from bugz.cli import BugzError, PrettyBugz
++from bugz.clparser import make_parser, get_kwds
+ 
+ def main():
+-	if len(sys.argv) < 2:
+-		PrettyBugz.help()
+-		sys.exit(-1)
+-
+-	cmd = sys.argv[1]
+-
+-	parser = OptionParser(version = '%%prog %s' % __version__)
+-
+-	global_opts = PrettyBugz.options
+-	for x in global_opts.values():
+-		parser.add_option(x)
+-
+-	if cmd == '--help' or cmd == '-h' or cmd == 'help':
+-		PrettyBugz.help()
+-		sys.exit(0)
+-	elif cmd == '--version' :
+-		parser.print_version()
+-		sys.exit(0)
+-
+-	cmd_func = getattr(PrettyBugz, cmd, None)
+-	if cmd_func is None:
+-		print '!! Error: Unable to recognise command: %s' % cmd
+-		print
+-		PrettyBugz.help()
+-		sys.exit(-1)
+-
+-	cmd_options = getattr(cmd_func, "options", {})
+-	cmd_args = getattr(cmd_func, "args", "[options]")
+-	parser.set_description(cmd_func.__doc__)
+-	parser.set_usage('%%prog %s %s' % (cmd, cmd_args))
+-
+-	for x in cmd_options.values():
+-		parser.add_option(x)
++	parser = make_parser()
+ 
+ 	# parse options
+-	opts, args = parser.parse_args(sys.argv[2:])
+-
+-	# separate bugz options and cmd options
+-	bugz_kwds = {}
+-	for name, opt in global_opts.items():
+-		try:
+-			bugz_kwds[name] = getattr(opts, name)
+-		except AttributeError:
+-			pass
+-
+-	cmd_kwds = {}
+-	for name, opt in cmd_options.items():
+-		try:
+-			cmd_kwds[name] = getattr(opts, name)
+-		except AttributeError:
+-			pass
++	args = parser.parse_args()
++	(bugz_kwds, cmd_kwds) = get_kwds(args)
+ 
+ 	try:
+ 		bugz = PrettyBugz(**bugz_kwds)
+-		getattr(bugz, cmd)(*args, **cmd_kwds)
++		args.func(bugz, **cmd_kwds)
+ 
+ 	except BugzError, e:
+ 		print ' ! Error: %s' % e
+-		print
+-		parser.print_help()
+ 		sys.exit(-1)
+ 
+ 	except TypeError, e:
+ 		print ' ! Error: Incorrect number of arguments supplied'
+ 		print
+ 		traceback.print_exc()
+-		parser.print_help()
+ 		sys.exit(-1)
+ 
+ 	except RuntimeError, e:
+diff --git a/bugz/bugzilla.py b/bugz/bugzilla.py
+index 7e1a2a9..2134de6 100644
+--- a/bugz/bugzilla.py
++++ b/bugz/bugzilla.py
+@@ -7,6 +7,7 @@ import locale
+ import mimetypes
+ import os
+ import re
++import sys
+ 
+ from cookielib import LWPCookieJar, CookieJar
+ from cStringIO import StringIO
+@@ -84,6 +85,8 @@ def get_content_type(filename):
+ #
+ # Override the behaviour of elementtree and allow us to
+ # force the encoding to utf-8
++# Not needed in Python 2.7, since ElementTree.XMLTreeBuilder uses the forced
++# encoding.
+ #
+ 
+ class ForcedEncodingXMLTreeBuilder(ElementTree.XMLTreeBuilder):
+@@ -235,7 +238,7 @@ class Bugz:
+ 			base64string = base64.encodestring('%s:%s' % (self.httpuser, self.httppassword))[:-1]
+ 			req.add_header("Authorization", "Basic %s" % base64string)
+ 		resp = self.opener.open(req)
+-		re_request_login = re.compile(r'<title>.*Log in to Bugzilla</title>')
++		re_request_login = re.compile(r'<title>.*Log in to .*</title>')
+ 		if not re_request_login.search(resp.read()):
+ 			self.log('Already logged in.')
+ 			self.authenticated = True
+@@ -255,6 +258,8 @@ class Bugz:
+ 		qparams = config.params['auth'].copy()
+ 		qparams['Bugzilla_login'] = self.user
+ 		qparams['Bugzilla_password'] = self.password
++		if not self.forget:
++			qparams['Bugzilla_remember'] = 'on'
+ 
+ 		req_url = urljoin(self.base, config.urls['auth'])
+ 		req = Request(req_url, urlencode(qparams), config.headers)
+@@ -285,7 +290,7 @@ class Bugz:
+ 				self.log('Unknown field: ' + field)
+ 				columns.append(field)
+ 		for row in rows[1:]:
+-			if row[0].find("Missing Search") != -1:
++			if "Missing Search" in row[0]:
+ 				self.log('Bugzilla error (Missing search found)')
+ 				return None
+ 			fields = {}
+@@ -439,9 +444,25 @@ class Bugz:
+ 			req.add_header("Authorization", "Basic %s" % base64string)
+ 		resp = self.opener.open(req)
+ 
+-		fd = StringIO(resp.read())
++		data = resp.read()
++		# Get rid of control characters.
++		data = re.sub('[\x00-\x08\x0e-\x1f\x0b\x0c]', '', data)
++		fd = StringIO(data)
++
+ 		# workaround for ill-defined XML templates in bugzilla 2.20.2
+-		parser = ForcedEncodingXMLTreeBuilder(encoding = 'utf-8')
++		(major_version, minor_version) = \
++		    (sys.version_info[0], sys.version_info[1])
++		if major_version > 2 or \
++			    (major_version == 2 and minor_version >= 7):
++			# If this is 2.7 or greater, then XMLTreeBuilder
++			# does what we want.
++			parser_class = ElementTree.XMLParser
++		else:
++			# Running under Python 2.6, so we need to use our
++			# subclass of XMLTreeBuilder instead.
++			parser_class = ForcedEncodingXMLTreeBuilder
++		parser = parser_class(encoding = 'utf-8')
++
+ 		etree = ElementTree.parse(fd, parser)
+ 		bug = etree.find('.//bug')
+ 		if bug and bug.attrib.has_key('error'):
+@@ -517,7 +538,7 @@ class Bugz:
+ 		FIELDS = ('bug_file_loc', 'bug_severity', 'short_desc', 'bug_status',
+ 				'status_whiteboard', 'keywords',
+ 				'op_sys', 'priority', 'version', 'target_milestone',
+-				'assigned_to', 'rep_platform', 'product', 'component')
++				'assigned_to', 'rep_platform', 'product', 'component', 'token')
+ 
+ 		FIELDS_MULTI = ('blocked', 'dependson')
+ 
+@@ -637,6 +658,11 @@ class Bugz:
+ 
+ 		try:
+ 			resp = self.opener.open(req)
++			re_error = re.compile(r'id="error_msg".*>([^<]+)<')
++			error = re_error.search(resp.read())
++			if error:
++				print error.group(1)
++				return []
+ 			return modified
+ 		except:
+ 			return []
+@@ -753,7 +779,7 @@ class Bugz:
+ 		return 0
+ 
+ 	def attach(self, bugid, title, description, filename,
+-			content_type = 'text/plain'):
++			content_type = 'text/plain', ispatch = False):
+ 		"""Attach a file to a bug.
+ 
+ 		@param bugid: bug id
+@@ -777,7 +803,11 @@ class Bugz:
+ 		qparams['bugid'] = bugid
+ 		qparams['description'] = title
+ 		qparams['comment'] = description
+-		qparams['contenttypeentry'] = content_type
++		if ispatch:
++			qparams['ispatch'] = '1'
++			qparams['contenttypeentry'] = 'text/plain'
++		else:
++			qparams['contenttypeentry'] = content_type
+ 
+ 		filedata = [('data', filename, open(filename).read())]
+ 		content_type, body = encode_multipart_formdata(qparams.items(),
+diff --git a/bugz/cli.py b/bugz/cli.py
+index e97da1b..8f25450 100644
+--- a/bugz/cli.py
++++ b/bugz/cli.py
+@@ -8,8 +8,6 @@ import sys
+ import tempfile
+ import textwrap
+ 
+-from optparse import OptionParser
+-from optparse import make_option
+ from urlparse import urljoin
+ 
+ try:
+@@ -122,43 +120,7 @@ def block_edit(comment, comment_from = ''):
+ class BugzError(Exception):
+ 	pass
+ 
+-#
+-# ugly optparse callbacks (really need to integrate this somehow)
+-#
+-
+-def modify_opt_fixed(opt, opt_str, val, parser):
+-	parser.values.status = 'RESOLVED'
+-	parser.values.resolution = 'FIXED'
+-
+-def modify_opt_invalid(opt, opt_str, val, parser):
+-	parser.values.status = 'RESOLVED'
+-	parser.values.resolution = 'INVALID'
+-
+ class PrettyBugz(Bugz):
+-	options = {
+-		'base': make_option('-b', '--base', type='string',
+-							default = 'https://bugs.gentoo.org/',
+-							help = 'Base URL of Bugzilla'),
+-		'user': make_option('-u', '--user', type='string',
+-							help = 'Username for commands requiring authentication'),
+-		'password': make_option('-p', '--password', type='string',
+-							help = 'Password for commands requiring authentication'),
+-		'httpuser': make_option('-H', '--httpuser', type='string',
+-							help = 'Username for basic http auth'),
+-		'httppassword': make_option('-P', '--httppassword', type='string',
+-							help = 'Password for basic http auth'),
+-		'forget': make_option('-f', '--forget', action='store_true',
+-							help = 'Forget login after execution'),
+-		'columns': make_option('--columns', type='int', default = 0,
+-							help = 'Maximum number of columns output should use'),
+-		'encoding': make_option('--encoding',
+-							help = 'Output encoding (default: utf-8).'),
+-		'skip_auth': make_option('--skip-auth', action='store_true',
+-							default = False, help = 'Skip Authentication.'),
+-		'quiet': make_option('-q', '--quiet', action='store_true',
+-							default = False, help = 'Quiet mode'),
+-	}
+-
+ 	def __init__(self, base, user = None, password =None, forget = False,
+ 			columns = 0, encoding = '', skip_auth = False,
+ 			quiet = False, httpuser = None, httppassword = None ):
+@@ -195,10 +157,11 @@ class PrettyBugz(Bugz):
+ 	def get_input(self, prompt):
+ 		return raw_input(prompt)
+ 
+-	def search(self, *args, **kwds):
++	def search(self, **kwds):
+ 		"""Performs a search on the bugzilla database with the keywords given on the title (or the body if specified).
+ 		"""
+-		search_term = ' '.join(args).strip()
++		search_term = ' '.join(kwds['terms']).strip()
++		del kwds['terms']
+ 		show_status = kwds['show_status']
+ 		del kwds['show_status']
+ 		show_url = kwds['show_url']
+@@ -232,41 +195,6 @@ class PrettyBugz(Bugz):
+ 
+ 		self.listbugs(result, show_url, show_status)
+ 
+-	search.args = "<search term> [options..]"
+-	search.options = {
+-		'order': make_option('-o', '--order', type='choice',
+-								choices = config.choices['order'].keys(),
+-								default = 'number'),
+-		'assigned_to': make_option('-a', '--assigned-to',
+-								help = 'email the bug is assigned to'),
+-		'reporter': make_option('-r', '--reporter',
+-								help = 'email the bug was reported by'),
+-		'cc': make_option('--cc',help = 'Restrict by CC email address'),
+-		'commenter': make_option('--commenter',help = 'email that commented the bug'),
+-		'status': make_option('-s', '--status', action='append',
+-								help = 'Bug status (for multiple choices,'
+-								'use --status=NEW --status=ASSIGNED) or --status=all for all statuses'),
+-		'severity': make_option('--severity', action='append',
+-								choices = config.choices['severity'],
+-								help = 'Restrict by severity.'),
+-		'priority': make_option('--priority', action='append',
+-								choices = config.choices['priority'].values(),
+-								help = 'Restrict by priority (1 or more)'),
+-		'comments': make_option('-c', '--comments',  action='store_true',
+-								help = 'Search comments instead of title'),
+-		'product': make_option('--product', action='append',
+-								help = 'Restrict by product (1 or more)'),
+-		'component': make_option('-C', '--component', action='append',
+-								help = 'Restrict by component (1 or more)'),
+-		'keywords': make_option('-k', '--keywords', help = 'Bug keywords'),
+-		'whiteboard': make_option('-w', '--whiteboard',
+-								help = 'Status whiteboard'),
+-		'show_status': make_option('--show-status', help='show status of bugs',
+-								action = 'store_true', default = False),
+-		'show_url': make_option('--show-url', help='Show bug id as a url.',
+-								action = 'store_true', default = False),
+-	}
+-
+ 	def namedcmd(self, command, show_status=False, show_url=False):
+ 		"""Run a command stored in Bugzilla by name."""
+ 		log_msg = 'Running namedcmd \'%s\''%command
+@@ -280,14 +208,6 @@ class PrettyBugz(Bugz):
+ 
+ 		self.listbugs(result, show_url, show_status)
+ 
+-	namedcmd.args = "<command name>"
+-	namedcmd.options = {
+-		'show_status': make_option('--show-status', help='show status of bugs',
+-								action = 'store_true', default = False),
+-		'show_url': make_option('--show-url', help='Show bug id as a url.',
+-								action = 'store_true', default = False),
+-	}
+-
+ 	def get(self, bugid, comments = True, attachments = True):
+ 		""" Fetch bug details given the bug id """
+ 		self.log('Getting bug %s ..' % bugid)
+@@ -384,13 +304,6 @@ class PrettyBugz(Bugz):
+ 				i += 1
+ 			print
+ 
+-	get.args = "<bug_id> [options..]"
+-	get.options = {
+-		'comments': make_option("-n", "--no-comments", dest = 'comments',
+-								action="store_false", default = True,
+-								help = 'Do not show comments'),
+-	}
+-
+ 	def post(self, product = None, component = None,
+ 			title = None, description = None, assigned_to = None,
+ 			cc = None, url = None, keywords = None,
+@@ -579,42 +492,6 @@ class PrettyBugz(Bugz):
+ 		else:
+ 			raise RuntimeError('Failed to submit bug')
+ 
+-	post.args = "[options]"
+-	post.options = {
+-		'product': make_option('--product', help = 'Product'),
+-		'component': make_option('--component', help = 'Component'),
+-		'prodversion': make_option('--prodversion',
+-									help = 'Version of the product'),
+-		'title': make_option('-t', '--title', help = 'Title of bug'),
+-		'description': make_option('-d', '--description',
+-									help = 'Description of the bug'),
+-		'description_from': make_option('-F' , '--description-from',
+-									help = 'Description from contents of'
+-									' file'),
+-		'append_command': make_option('--append-command',
+-									help = 'Append the output of a command to the description.'),
+-		'assigned_to': make_option('-a', '--assigned-to',
+-									help = 'Assign bug to someone other than '
+-									'the default assignee'),
+-		'cc': make_option('--cc', help = 'Add a list of emails to CC list'),
+-		'url': make_option('-U', '--url',
+-									help = 'URL associated with the bug'),
+-		'dependson': make_option('--depends-on', dest='dependson', help = 'Add a list of bug dependencies'),
+-		'blocked': make_option('--blocked', help = 'Add a list of blocker bugs'),
+-		'keywords': make_option('-k', '--keywords', help = 'List of bugzilla keywords'),
+-		'batch': make_option('--batch', action="store_true",
+-									help = 'do not prompt for any values'),
+-		'default_confirm': make_option('--default-confirm',
+-									choices = ['y','Y','n','N'],
+-									default = 'y',
+-									help = 'default answer to confirmation question (y/n)'),
+-		'priority': make_option('--priority',
+-								choices=config.choices['priority'].values()),
+-		'severity': make_option('-S', '--severity',
+-								choices=config.choices['severity']),
+-	}
+-
+-
+ 	def modify(self, bugid, **kwds):
+ 		"""Modify an existing bug (eg. adding a comment or changing resolution.)"""
+ 		if 'comment_from' in kwds:
+@@ -637,6 +514,15 @@ class PrettyBugz(Bugz):
+ 				kwds['comment'] = block_edit('Enter comment:')
+ 			del kwds['comment_editor']
+ 
++		if kwds['fixed']:
++			kwds['STATUS'] = 'CLOSED'
++			kwds['resolution'] = 'FIXED'
++		del kwds['fixed']
++
++		if kwds['invalid']:
++			kwds['STATUS'] = 'CLOSED'
++			kwds['resolution'] = 'INVALID'
++		del kwds['invalid']
+ 		result = Bugz.modify(self, bugid, **kwds)
+ 		if not result:
+ 			raise RuntimeError('Failed to modify bug')
+@@ -645,53 +531,6 @@ class PrettyBugz(Bugz):
+ 			for field, value in result:
+ 				self.log('  %-12s: %s' % (field, value))
+ 
+-
+-	modify.args = "<bug_id> [options..]"
+-	modify.options = {
+-		'title': make_option('-t', '--title', help = 'Set title of bug'),
+-		'comment_from': make_option('-F', '--comment-from',
+-									help = 'Add comment from file.  If -C is also specified, the editor will be opened with this file as its contents.'),
+-		'comment_editor': make_option('-C', '--comment-editor',
+-									action='store_true', default = False,
+-									help = 'Add comment via default editor'),
+-		'comment': make_option('-c', '--comment', help = 'Add comment to bug'),
+-		'url': make_option('-U', '--url', help = 'Set URL field of bug'),
+-		'status': make_option('-s', '--status',
+-									choices=config.choices['status'].values(),
+-									help = 'Set new status of bug (eg. RESOLVED)'),
+-		'resolution': make_option('-r', '--resolution',
+-									choices=config.choices['resolution'].values(),
+-									help = 'Set new resolution (only if status = RESOLVED)'),
+-		'assigned_to': make_option('-a', '--assigned-to'),
+-		'duplicate': make_option('-d', '--duplicate', type='int', default=0),
+-		'priority': make_option('--priority',
+-								choices=config.choices['priority'].values()),
+-		'severity': make_option('-S', '--severity',
+-								choices=config.choices['severity']),
+-		'fixed': make_option('--fixed', action='callback',
+-								callback = modify_opt_fixed,
+-								help = "Mark bug as RESOLVED, FIXED"),
+-		'invalid': make_option('--invalid', action='callback',
+-								callback = modify_opt_invalid,
+-								help = "Mark bug as RESOLVED, INVALID"),
+-		'add_cc': make_option('--add-cc', action = 'append',
+-								help = 'Add an email to the CC list'),
+-		'remove_cc': make_option('--remove-cc', action = 'append',
+-								help = 'Remove an email from the CC list'),
+-		'add_dependson': make_option('--add-dependson', action = 'append',
+-								help = 'Add a bug to the depends list'),
+-		'remove_dependson': make_option('--remove-dependson', action = 'append',
+-								help = 'Remove a bug from the depends list'),
+-		'add_blocked': make_option('--add-blocked', action = 'append',
+-								help = 'Add a bug to the blocked list'),
+-		'remove_blocked': make_option('--remove-blocked', action = 'append',
+-								help = 'Remove a bug from the blocked list'),
+-		'whiteboard': make_option('-w', '--whiteboard',
+-								help = 'Set Status whiteboard'),
+-		'keywords': make_option('-k', '--keywords',
+-								help = 'Set bug keywords'),
+-		}
+-
+ 	def attachment(self, attachid, view = False):
+ 		""" Download or view an attachment given the id."""
+ 		self.log('Getting attachment %s' % attachid)
+@@ -713,30 +552,14 @@ class PrettyBugz(Bugz):
+ 
+ 			open(safe_filename, 'wb').write(result['fd'].read())
+ 
+-	attachment.args = "<attachid> [-v]"
+-	attachment.options = {
+-		'view': make_option('-v', '--view', action="store_true",
+-							default = False,
+-							help = "Print attachment rather than save")
+-	}
+-
+-	def attach(self, bugid, filename, content_type = 'text/plain', description = None):
++	def attach(self, bugid, filename, content_type = 'text/plain', patch = False, description = None):
+ 		""" Attach a file to a bug given a filename. """
+ 		if not os.path.exists(filename):
+ 			raise BugzError('File not found: %s' % filename)
+ 		if not description:
+ 			description = block_edit('Enter description (optional)')
+ 		result = Bugz.attach(self, bugid, filename, description, filename,
+-				content_type)
+-
+-	attach.args = "<bugid> <filename> [-c=<mimetype>] [-d=<description>]"
+-	attach.options = {
+-		'content_type': make_option('-c', '--content-type',
+-									default='text/plain',
+-									help = 'Mimetype of the file (default: text/plain)'),
+-		'description': make_option('-d', '--description',
+-									help = 'A description of the attachment.')
+-	}
++				content_type, patch)
+ 
+ 	def listbugs(self, buglist, show_url=False, show_status=False):
+ 		for row in buglist:
+@@ -760,27 +583,3 @@ class PrettyBugz(Bugz):
+ 				print line[:self.columns]
+ 
+ 		self.log("%i bug(s) found." % len(buglist))
+-
+-	@classmethod
+-	def help(self):
+-		print 'Usage: bugz <subcommand> [parameter(s)] [options..]'
+-		print
+-		print 'Subcommands:'
+-		print '  search      Search for bugs in bugzilla'
+-		print '  get         Get a bug from bugzilla'
+-		print '  attachment  Get an attachment from bugzilla'
+-		print '  post        Post a new bug into bugzilla'
+-		print '  modify      Modify a bug (eg. post a comment)'
+-		print '  attach      Attach file to a bug'
+-		print '  namedcmd    Run a stored search,'
+-		print
+-		print 'Examples:'
+-		print '  bugz get 12345'
+-		print '  bugz search python --assigned-to liquidx at gentoo.org'
+-		print '  bugz attachment 5000 --view'
+-		print '  bugz attach 140574 python-2.4.3.ebuild'
+-		print '  bugz modify 140574 -c "Me too"'
+-		print '  bugz namedcmd "Amd64 stable"'
+-		print
+-		print 'For more information on subcommands, run:'
+-		print '  bugz <subcommand> --help'
+diff --git a/bugz/clparser.py b/bugz/clparser.py
+new file mode 100644
+index 0000000..f9bdca9
+--- /dev/null
++++ b/bugz/clparser.py
+@@ -0,0 +1,283 @@
++#!/usr/bin/env python
++
++import argparse
++
++from bugz import __version__
++from bugz.cli import PrettyBugz
++from bugz.config import config
++
++def make_attach_parser(subparsers):
++	attach_parser = subparsers.add_parser('attach',
++		help = 'attach file to a bug')
++	attach_parser.add_argument('bugid',
++		help = 'the ID of the bug where the file should be attached')
++	attach_parser.add_argument('filename',
++		help = 'the name of the file to attach')
++	attach_parser.add_argument('-c', '--content-type',
++		default='text/plain',
++		help = 'mimetype of the file (default: text/plain)')
++	attach_parser.add_argument('-d', '--description',
++		help = 'a description of the attachment.')
++	attach_parser.add_argument('-p', '--patch',
++		action='store_true',
++	help = 'attachment is a patch')
++	attach_parser.set_defaults(func = PrettyBugz.attach)
++
++def make_attachment_parser(subparsers):
++	attachment_parser = subparsers.add_parser('attachment',
++		help = 'get an attachment from bugzilla')
++	attachment_parser.add_argument('attachid',
++		help = 'the ID of the attachment')
++	attachment_parser.add_argument('-v', '--view',
++		action="store_true",
++		default = False,
++		help = 'print attachment rather than save')
++	attachment_parser.set_defaults(func = PrettyBugz.attachment)
++
++def make_get_parser(subparsers):
++	get_parser = subparsers.add_parser('get',
++		help = 'get a bug from bugzilla')
++	get_parser.add_argument('bugid',
++		help = 'the ID of the bug to retrieve.')
++	get_parser.add_argument("-a", "--no-attachments",
++		action="store_false",
++		default = True,
++		help = 'do not show attachments',
++		dest = 'attachments')
++	get_parser.add_argument("-n", "--no-comments",
++		action="store_false",
++		default = True,
++		help = 'do not show comments',
++		dest = 'comments')
++	get_parser.set_defaults(func = PrettyBugz.get)
++
++def make_modify_parser(subparsers):
++	modify_parser = subparsers.add_parser('modify',
++		help = 'modify a bug (eg. post a comment)')
++	modify_parser.add_argument('bugid',
++		help = 'the ID of the bug to modify')
++	modify_parser.add_argument('-a', '--assigned-to',
++		help = 'change assignee for this bug')
++	modify_parser.add_argument('-C', '--comment-editor',
++		action='store_true',
++		help = 'add comment via default editor')
++	modify_parser.add_argument('-F', '--comment-from',
++		help = 'add comment from file.  If -C is also specified, the editor will be opened with this file as its contents.')
++	modify_parser.add_argument('-c', '--comment',
++		help = 'add comment from command line')
++	modify_parser.add_argument('-d', '--duplicate',
++		type = int,
++		default = 0,
++		help = 'this bug is a duplicate')
++	modify_parser.add_argument('-k', '--keywords',
++		help = 'set bug keywords'),
++	modify_parser.add_argument('--priority',
++		choices=config.choices['priority'].values(),
++		help = 'change the priority for this bug')
++	modify_parser.add_argument('-r', '--resolution',
++		choices=config.choices['resolution'].values(),
++		help = 'set new resolution (only if status = RESOLVED)')
++	modify_parser.add_argument('-s', '--status',
++		choices=config.choices['status'].values(),
++		help = 'set new status of bug (eg. RESOLVED)')
++	modify_parser.add_argument('-S', '--severity',
++		choices=config.choices['severity'],
++		help = 'set severity for this bug')
++	modify_parser.add_argument('-t', '--title',
++		help = 'set title of bug')
++	modify_parser.add_argument('-U', '--url',
++		help = 'set URL field of bug')
++	modify_parser.add_argument('-w', '--whiteboard',
++		help = 'set Status whiteboard'),
++	modify_parser.add_argument('--add-cc',
++		action = 'append',
++		help = 'add an email to the CC list')
++	modify_parser.add_argument('--remove-cc',
++		action = 'append',
++		help = 'remove an email from the CC list')
++	modify_parser.add_argument('--add-dependson',
++		action = 'append',
++		help = 'add a bug to the depends list')
++	modify_parser.add_argument('--remove-dependson',
++		action = 'append',
++		help = 'remove a bug from the depends list')
++	modify_parser.add_argument('--add-blocked',
++		action = 'append',
++		help = 'add a bug to the blocked list')
++	modify_parser.add_argument('--remove-blocked',
++		action = 'append',
++		help = 'remove a bug from the blocked list')
++	modify_parser.add_argument('--fixed',
++		action='store_true',
++		help = 'mark bug as RESOLVED, FIXED')
++	modify_parser.add_argument('--invalid',
++		action='store_true',
++		help = 'mark bug as RESOLVED, INVALID')
++	modify_parser.set_defaults(func = PrettyBugz.modify)
++
++def make_namedcmd_parser(subparsers):
++	namedcmd_parser = subparsers.add_parser('namedcmd',
++		help = 'run a stored search')
++	namedcmd_parser.add_argument('command',
++		help = 'the name of the stored search')
++	namedcmd_parser.add_argument('--show-status',
++		action = 'store_true',
++		help = 'show status of bugs')
++	namedcmd_parser.add_argument('--show-url',
++		action = 'store_true',
++		help = 'show bug id as a url')
++	namedcmd_parser.set_defaults(func = PrettyBugz.namedcmd)
++
++def make_post_parser(subparsers):
++	post_parser = subparsers.add_parser('post',
++		help = 'post a new bug into bugzilla')
++	post_parser.add_argument('--product',
++		help = 'product')
++	post_parser.add_argument('--component',
++		help = 'component')
++	post_parser.add_argument('--prodversion',
++		help = 'version of the product')
++	post_parser.add_argument('-t', '--title',
++		help = 'title of bug')
++	post_parser.add_argument('-d', '--description',
++		help = 'description of the bug')
++	post_parser.add_argument('-F' , '--description-from',
++		help = 'description from contents of file')
++	post_parser.add_argument('--append-command',
++		help = 'append the output of a command to the description')
++	post_parser.add_argument('-a', '--assigned-to',
++		help = 'assign bug to someone other than the default assignee')
++	post_parser.add_argument('--cc',
++		help = 'add a list of emails to CC list')
++	post_parser.add_argument('-U', '--url',
++		help = 'URL associated with the bug')
++	post_parser.add_argument('--depends-on',
++		help = 'add a list of bug dependencies',
++		dest='dependson')
++	post_parser.add_argument('--blocked',
++		help = 'add a list of blocker bugs')
++	post_parser.add_argument('-k', '--keywords',
++		help = 'list of bugzilla keywords')
++	post_parser.add_argument('--batch',
++		action="store_true",
++		help = 'do not prompt for any values')
++	post_parser.add_argument('--default-confirm',
++		choices = ['y','Y','n','N'],
++		default = 'y',
++		help = 'default answer to confirmation question')
++	post_parser.add_argument('--priority',
++		choices=config.choices['priority'].values(),
++		help = 'set priority for the new bug')
++	post_parser.add_argument('-S', '--severity',
++		choices=config.choices['severity'],
++		help = 'set the severity for the new bug')
++	post_parser.set_defaults(func = PrettyBugz.post)
++
++def make_search_parser(subparsers):
++	search_parser = subparsers.add_parser('search',
++		help = 'search for bugs in bugzilla')
++	search_parser.add_argument('terms',
++		nargs='*',
++		help = 'strings to search for in title or body')
++	search_parser.add_argument('-o', '--order',
++		choices = config.choices['order'].keys(),
++		default = 'number',
++		help = 'display bugs in this order')
++	search_parser.add_argument('-a', '--assigned-to',
++		help = 'email the bug is assigned to')
++	search_parser.add_argument('-r', '--reporter',
++		help = 'email the bug was reported by')
++	search_parser.add_argument('--cc',
++		help = 'restrict by CC email address')
++	search_parser.add_argument('--commenter',
++		help = 'email that commented the bug')
++	search_parser.add_argument('-s', '--status',
++		action='append',
++		help = 'restrict by status (one or more, use all for all statuses)')
++	search_parser.add_argument('--severity',
++		action='append',
++		choices = config.choices['severity'],
++		help = 'restrict by severity (one or more)')
++	search_parser.add_argument('--priority',
++		action='append',
++		choices = config.choices['priority'].values(),
++		help = 'restrict by priority (one or more)')
++	search_parser.add_argument('-c', '--comments',
++		action='store_true',
++		default=None,
++		help = 'search comments instead of title')
++	search_parser.add_argument('--product',
++		action='append',
++		help = 'restrict by product (one or more)')
++	search_parser.add_argument('-C', '--component',
++		action='append',
++		help = 'restrict by component (1 or more)')
++	search_parser.add_argument('-k', '--keywords',
++		help = 'restrict by keywords')
++	search_parser.add_argument('-w', '--whiteboard',
++		help = 'status whiteboard')
++	search_parser.add_argument('--show-status',
++		action = 'store_true',
++		help='show status of bugs')
++	search_parser.add_argument('--show-url',
++		action = 'store_true',
++		help='show bug id as a url.')
++	search_parser.set_defaults(func = PrettyBugz.search)
++
++def make_parser():
++	parser = argparse.ArgumentParser(
++		epilog = 'use -h after a sub-command for sub-command specific help')
++	parser.add_argument('-b', '--base',
++		default = 'https://bugs.gentoo.org/',
++		help = 'base URL of Bugzilla')
++	parser.add_argument('-u', '--user',
++		help = 'username for commands requiring authentication')
++	parser.add_argument('-p', '--password',
++		help = 'password for commands requiring authentication')
++	parser.add_argument('-H', '--httpuser',
++		help = 'username for basic http auth')
++	parser.add_argument('-P', '--httppassword',
++		help = 'password for basic http auth')
++	parser.add_argument('-f', '--forget',
++		action='store_true',
++		help = 'forget login after execution')
++	parser.add_argument('-q', '--quiet',
++		action='store_true',
++		default = False,
++		help = 'quiet mode')
++	parser.add_argument('--columns', 
++		type = int,
++		default = 0,
++		help = 'maximum number of columns output should use')
++	parser.add_argument('--encoding',
++		help = 'output encoding (default: utf-8).')
++	parser.add_argument('--skip-auth',
++		action='store_true',
++		default = False,
++		help = 'skip Authentication.')
++	parser.add_argument('--version',
++		action='version',
++		help='show program version and exit',
++		version='%(prog)s ' + __version__)
++	subparsers = parser.add_subparsers(help = 'help for sub-commands')
++	make_attach_parser(subparsers)
++	make_attachment_parser(subparsers)
++	make_get_parser(subparsers)
++	make_modify_parser(subparsers)
++	make_namedcmd_parser(subparsers)
++	make_post_parser(subparsers)
++	make_search_parser(subparsers)
++	return parser
++
++def get_kwds(args):
++	bugz = {}
++	cmd = {}
++	global_attrs = ['user', 'password', 'httpuser', 'httppassword', 'forget',
++		'base', 'columns', 'encoding', 'quiet', 'skip_auth']
++	for attr in dir(args):
++		if attr[0] != '_' and attr != 'func':
++			if attr in global_attrs:
++				bugz[attr] = getattr(args,attr)
++			else:
++				cmd[attr] = getattr(args,attr)
++	return bugz, cmd
+diff --git a/bugz/config.py b/bugz/config.py
+index 4083e48..824c2ad 100644
+--- a/bugz/config.py
++++ b/bugz/config.py
+@@ -54,6 +54,7 @@ class BugzConfig:
+ 
+ 		'attach_post': {
+ 		'action': 'insert',
++		'ispatch': '',
+ 		'contenttypemethod': 'manual',
+ 		'bugid': '',
+ 		'description': '',
+diff --git a/contrib/zsh-completion b/contrib/zsh-completion
+index ee4bef6..c88ebff 100644
+--- a/contrib/zsh-completion
++++ b/contrib/zsh-completion
+@@ -14,7 +14,7 @@ _bugz() {
+     '(-P --httppassword)'{-P,--httppassword}'[basic http auth password (if required)]:password: '
+     '(-f --forget)'{-f,--forget}'[do not remember authentication]'
+     '--columns[number of columns to use when displaying output]:number: '
+-    '(--skip-auth)'{--skip-auth}'[do not authenticate]'
++    '--skip-auth[do not authenticate]'
+     '(-q --quiet)'{-q,--quiet}'[do not display status messages]'
+   )
+   _bugz_commands=(



More information about the SM-Commit mailing list