[Python-modules-commits] [python-bugzilla] 01/05: New upstream version 2.1.0

Sergio Durigan Junior sergiodj-guest at moszumanska.debian.org
Mon Aug 7 23:55:26 UTC 2017


This is an automated email from the git hooks/post-receive script.

sergiodj-guest pushed a commit to branch master
in repository python-bugzilla.

commit f43778a7b15f0933999b18c23e32a467f8881274
Author: Sergio Durigan Junior <sergiodj at sergiodj.net>
Date:   Mon Aug 7 17:56:43 2017 -0400

    New upstream version 2.1.0
---
 CONTRIBUTING.md                      |   14 +-
 MANIFEST.in                          |    5 +-
 NEWS.md                              |   80 +++
 PKG-INFO                             |    2 +-
 README.md                            |    2 +
 bin/bugzilla                         | 1083 ++++++++++++++--------------------
 bugzilla.1                           |  336 ++++-------
 bugzilla/__init__.py                 |  134 +----
 bugzilla/apiversion.py               |    2 +-
 bugzilla/base.py                     | 1008 ++++++++++++++++---------------
 bugzilla/bug.py                      |  168 ++----
 bugzilla/bugzilla3.py                |   34 --
 bugzilla/bugzilla4.py                |   47 --
 bugzilla/oldclasses.py               |   23 +
 bugzilla/rhbugzilla.py               |  293 ++-------
 bugzilla/transport.py                |  195 ++++++
 bz-api-notes.txt                     |  123 ----
 examples/apikey.py                   |   29 +
 examples/bug_autorefresh.py          |   59 ++
 examples/create.py                   |   45 ++
 examples/getbug.py                   |   45 ++
 examples/query.py                    |   88 +++
 examples/update.py                   |   64 ++
 python-bugzilla.spec                 |   56 +-
 python_bugzilla.egg-info/PKG-INFO    |    2 +-
 python_bugzilla.egg-info/SOURCES.txt |   14 +-
 python_bugzilla.egg-info/pbr.json    |    1 -
 setup.py                             |   13 +-
 tests/__init__.py                    |   23 +-
 tests/bug.py                         |   10 +-
 tests/createbug.py                   |    4 +-
 tests/misc.py                        |  126 ++--
 tests/modify.py                      |   48 +-
 tests/pep8.cfg                       |    4 +-
 tests/pylint.cfg                     |   20 +-
 tests/query.py                       |  148 ++---
 tests/ro_functional.py               |  153 +++--
 tests/rw_functional.py               |  416 +++++++------
 xmlrpc-api-notes.txt                 |  122 ++++
 39 files changed, 2535 insertions(+), 2504 deletions(-)

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index df1ab0b..5e093c0 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -6,15 +6,6 @@ dependencies, running the command line from git is as simple as doing:
     cd python-bugzilla.git
     ./bugzilla-cli [arguments]
 
-If you want to use pip and virtualenv to install a local development
-environment, use the following command.
-
-    source contrib/activate-dev-env [python2|python3]
-
-Then you can manually activate an environment with:
-
-    source dev-env-${NAME}/bin/activate
-
 
 # Running tests
 
@@ -37,7 +28,7 @@ Before running rw-functional tests, make sure you have logged into bugzilla
 using. These currently run against the test bugzilla instance at
 partner-bugzilla.redhat.com, and requires a valid login there:
 
-    bugzilla-cli --bugzilla=partner-bugzilla.redhat.com --user=$USER login
+    bugzilla-cli --bugzilla=partner-bugzilla.redhat.com --username=$USER login
     python setup.py test --rw-functional
 
 ## Testing across python versions
@@ -54,8 +45,7 @@ To test for pylint or pep8 violations, you can run:
 
     python setup.py pylint
 
-Note: This expects that you already have pylint and pep8 (installed when setting
-up virtualenv) installed.
+Note: This expects that you already have pylint and pep8 installed.
 
 
 # Patch Submission
diff --git a/MANIFEST.in b/MANIFEST.in
index db856ad..43b1452 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,6 +1,7 @@
-include COPYING CONTRIBUTING.md MANIFEST.in README.md
+include COPYING CONTRIBUTING.md MANIFEST.in README.md NEWS.md
 include bugzilla.1
-include bz-api-notes.txt
+include xmlrpc-api-notes.txt
 include python-bugzilla.spec
 include *requirements.txt
+recursive-include examples *.py
 recursive-include tests *.py *.txt *.cfg
diff --git a/NEWS.md b/NEWS.md
new file mode 100644
index 0000000..012156e
--- /dev/null
+++ b/NEWS.md
@@ -0,0 +1,80 @@
+# python-bugzilla release news
+
+## Release 2.1.0 (March 30, 2017)
+- Support for bugzilla 5 API Keys (Dustin J. Mitchell)
+- bugzillarc can be used to set default URL for the cli tool
+- Revive update_flags wrapper
+- Bug fixes and minor improvements
+
+## Release 2.0.0 (Feb 08 2017)
+
+This release contains several small to medium API breaks. I expect most users
+won't notice any difference. I previously outlined the changes here:
+
+https://lists.fedorahosted.org/archives/list/python-bugzilla@lists.fedorahosted.org/thread/WCYPOKJZFYOW7RRT44FCM5GQU26O56K4/
+
+The major changes are:
+
+- Several fixes for use with bugzilla 5
+- Bugzilla.bug_autorefresh now defaults to False
+- Credentials are now cached in ~/.cache/python-bugzilla/
+- bin/bugzilla was converted to argparse
+- bugzilla query --boolean_chart option is removed
+- Unify command line flags across sub commands
+
+## Release 1.2.2 (Sep 23 2015)
+
+- Switch hosting to http://github.com/python-bugzilla/python-bugzilla
+- Fix requests usage when ndg-httpsclient is installed (Arun Babu
+  Neelicattu)
+- Add non-rhbz support for getting bug comments (AJ Lewis)
+- Misc bugfixes and improvements
+
+## Release 1.2.1 (May 22 2015)
+
+- bin/bugzilla: Add --ensure-logged-in option
+- Fix get_products with bugzilla.redhat.com
+- A few other minor improvements
+
+## Release 1.2.0 (Apr 08 2015)
+
+- Add bugzilla new/query/modify --field flag (Arun Babu Neelicattu)
+- API support for ExternalBugs (Arun Babu Neelicattu, Brian Bouterse)
+- Add new/modify --alias support (Adam Williamson)
+- Bugzilla.logged_in now returns live state (Arun Babu Neelicattu)
+- Fix getbugs API with latest Bugzilla releases
+
+## Release 1.1.0 (Jun 01 2014)
+
+- Support for bugzilla tokens (Arun Babu Nelicattu)
+- bugzilla: Add query/modify --tags
+- bugzilla --login: Allow to login and run a command in one shot
+- bugzilla --no-cache-credentials: Don't use or save cached credentials
+  when using the CLI
+- Show bugzilla errors when login fails
+- Don't pull down attachments in bug.refresh(), need to get
+  bug.attachments manually
+- Add Bugzilla bug_autorefresh parameter.
+
+## Release 1.0.0 (Mar 25 2014)
+
+- Python 3 support (Arun Babu Neelicattu)
+- Port to python-requests (Arun Babu Neelicattu)
+- bugzilla: new: Add --keywords, --assigned_to, --qa_contact (Lon Hohberger)
+- bugzilla: query: Add --quicksearch, --savedsearch
+- bugzilla: query: Support saved searches with --from-url
+- bugzilla: --sub-component support for all relevant commands
+
+## Release 0.9.0 (Jun 19 2013)
+
+- CVE-2013-2191: Switch to pycurl to get SSL host and cert validation
+- bugzilla: modify: add --dependson (Don Zickus)
+- bugzilla: new: add --groups option (Paul Frields)
+- bugzilla: modify: Allow setting nearly every bug parameter
+- NovellBugzilla implementation removed, can't get it to work
+
+## Release 0.8.0 (Feb 16 2013)
+
+- Replace usage of non-upstream Red Hat bugzilla APIs with upstream replacements
+- Test suite improvements, nearly complete code coverage
+- Fix all open bug reports and RFEs
diff --git a/PKG-INFO b/PKG-INFO
index 946cdea..09afcab 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.0
 Name: python-bugzilla
-Version: 1.2.2
+Version: 2.1.0
 Summary: Bugzilla XMLRPC access module
 Home-page: https://github.com/python-bugzilla/python-bugzilla
 Author: Cole Robinson
diff --git a/README.md b/README.md
index df0186f..4742be9 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,8 @@ This was originally written specifically for Red Hat's Bugzilla instance
 and is used heavily at Red Hat and in Fedora, but it should still be
 generically useful.
 
+You can find some code examples in the [examples](examples) directory
+
 For questions about submitting bug reports or patches, see [CONTRIBUTING.md](CONTRIBUTING.md)
 
 Questions, comments, and discussions should go to our mailing: http://lists.fedorahosted.org/mailman/listinfo/python-bugzilla
diff --git a/bin/bugzilla b/bin/bugzilla
index 8397df9..28918a8 100755
--- a/bin/bugzilla
+++ b/bin/bugzilla
@@ -1,9 +1,10 @@
-#!/usr/bin/python -tt
+#!/usr/bin/env python
 #
 # bugzilla - a commandline frontend for the python bugzilla module
 #
-# Copyright (C) 2007, 2008, 2009, 2010, 2011 Red Hat Inc.
+# Copyright (C) 2007-2017 Red Hat Inc.
 # Author: Will Woods <wwoods at redhat.com>
+# Author: Cole Robinson <crobinso at redhat.com>
 #
 # This program is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by the
@@ -14,8 +15,8 @@
 from __future__ import print_function
 
 import locale
-from logging import DEBUG, INFO, WARN, StreamHandler, Formatter
-import optparse
+from logging import getLogger, DEBUG, INFO, WARN, StreamHandler, Formatter
+import argparse
 import os
 import re
 import socket
@@ -23,23 +24,25 @@ import sys
 import tempfile
 
 if hasattr(sys.version_info, "major") and sys.version_info.major >= 3:
-    # pylint: disable=F0401,W0622
+    # pylint: disable=F0401,W0622,E0611
     from xmlrpc.client import Fault, ProtocolError
+    from urllib.parse import urlparse
     basestring = (str, bytes)
 else:
     from xmlrpclib import Fault, ProtocolError
+    from urlparse import urlparse
 
 import requests.exceptions
 
 import bugzilla
 
-default_bz = 'https://bugzilla.redhat.com/xmlrpc.cgi'
+DEFAULT_BZ = 'https://bugzilla.redhat.com/xmlrpc.cgi'
 
 _is_unittest = bool(os.getenv("__BUGZILLA_UNITTEST"))
-cmdlist = ['login', 'new', 'query', 'modify', 'attach', 'info']
+_is_unittest_debug = bool(os.getenv("__BUGZILLA_UNITTEST_DEBUG"))
 format_field_re = re.compile("%{([a-z0-9_]+)(?::([^}]*))?}")
 
-log = bugzilla.log
+log = getLogger(bugzilla.__name__)
 handler = StreamHandler(sys.stderr)
 handler.setFormatter(Formatter(
     "[%(asctime)s] %(levelname)s (%(module)s:%(lineno)d) %(message)s",
@@ -60,11 +63,11 @@ def to_encoding(ustring):
 
     if hasattr(sys.version_info, "major") and sys.version_info.major >= 3:
         return string
-    else:
-        preferred = locale.getpreferredencoding()
-        if "PYTHON_BUGZILLA_TEST_SUITE" in os.environ:
-            preferred = "UTF-8"
-        return string.encode(preferred, 'replace')
+
+    preferred = locale.getpreferredencoding()
+    if _is_unittest:
+        preferred = "UTF-8"
+    return string.encode(preferred, 'replace')
 
 
 def open_without_clobber(name, *args):
@@ -89,528 +92,319 @@ def open_without_clobber(name, *args):
     return fobj
 
 
+def get_default_url():
+    """
+    Grab a default URL from bugzillarc [DEFAULT] url=X
+    """
+    from bugzilla.base import _open_bugzillarc
+    cfg = _open_bugzillarc()
+    if cfg:
+        cfgurl = cfg.defaults().get("url", None)
+        if cfgurl is not None:
+            log.debug("bugzillarc: found cli url=%s", cfgurl)
+            return cfgurl
+    return DEFAULT_BZ
+
+
 ##################
 # Option parsing #
 ##################
 
-def setup_parser():
-    u = ("%%prog [global options] COMMAND [command-options]"
-         "\n\nCommands: %s" % ', '.join(sorted(cmdlist)))
-    p = optparse.OptionParser(usage=u, version=bugzilla.__version__)
-    p.disable_interspersed_args()
-    p.epilog = 'Try "bugzilla COMMAND --help" for command-specific help.'
+def _setup_root_parser():
+    epilog = 'Try "bugzilla COMMAND --help" for command-specific help.'
+    p = argparse.ArgumentParser(epilog=epilog)
+
+    default_url = get_default_url()
 
     # General bugzilla connection options
-    p.add_option('--bugzilla', default=default_bz,
-            help="bugzilla XMLRPC URI. default: %s" % default_bz)
-    p.add_option("--nosslverify", dest="sslverify",
+    p.add_argument('--bugzilla', default=default_url,
+            help="bugzilla XMLRPC URI. default: %s" % default_url)
+    p.add_argument("--nosslverify", dest="sslverify",
                  action="store_false", default=True,
                  help="Don't error on invalid bugzilla SSL certificate")
 
-    p.add_option('--user', help="Optional bugzilla login username")
-    p.add_option('--password', help="Optional bugzilla login password")
-    p.add_option('--login', action="store_true",
+    p.add_argument('--login', action="store_true",
         help='Run interactive "login" before performing the '
              'specified command.')
-    p.add_option('--ensure-logged-in', action="store_true",
+    p.add_argument('--username', help="Log in with this username")
+    p.add_argument('--password', help="Log in with this password")
+
+    p.add_argument('--ensure-logged-in', action="store_true",
         help="Raise an error if we aren't logged in to bugzilla. "
              "Consider using this if you are depending on "
              "cached credentials, to ensure that when they expire the "
              "tool errors, rather than subtly change output.")
-    p.add_option('--no-cache-credentials',
+    p.add_argument('--no-cache-credentials',
         action='store_false', default=True, dest='cache_credentials',
         help="Don't save any bugzilla cookies or tokens to disk, and "
              "don't use any pre-existing credentials.")
 
-    p.add_option('--cookiefile', default=None,
+    p.add_argument('--cookiefile', default=None,
             help="cookie file to use for bugzilla authentication")
-    p.add_option('--tokenfile', default=None,
+    p.add_argument('--tokenfile', default=None,
             help="token file to use for bugzilla authentication")
 
-    p.add_option('--verbose', action='store_true',
+    p.add_argument('--verbose', action='store_true',
             help="give more info about what's going on")
-    p.add_option('--debug', action='store_true',
+    p.add_argument('--debug', action='store_true',
             help="output bunches of debugging info")
-
-    # Generate the man page, dump to stdout. Not for end users
-    p.add_option('--generate-man', action='store_true',
-            help=optparse.SUPPRESS_HELP)
+    p.add_argument('--version', action='version',
+                   version=bugzilla.__version__)
 
     # Allow user to specify BZClass to initialize. Kinda weird for the
     # CLI, I'd rather people file bugs about this so we can fix our detection.
     # So hide it from the help output but keep it for back compat
-    p.add_option('--bztype', default='auto', help=optparse.SUPPRESS_HELP)
+    p.add_argument('--bztype', default='auto', help=argparse.SUPPRESS)
 
     return p
 
 
-def setup_action_parser(action):
-    p = optparse.OptionParser(usage="%%prog %s [options]" % action)
-
-    if action == 'new':
-        p.set_description("Create a new bug report.")
-        p.add_option('-p', '--product', help="REQUIRED: product name")
-        p.add_option('-v', '--version', help="REQUIRED: product version")
-        p.add_option('-c', '--component', help="REQUIRED: component name")
-        p.add_option("--sub-component", help="Optional sub component name")
-        p.add_option('-s', '--short_desc', '--summary', dest='summary',
-                help="REQUIRED: bug summary")
-        p.add_option('-l', '--comment', dest='description',
-                help="initial bug comment")
-        p.add_option('-o', '--os', help="Operating system")
-        p.add_option('-a', '--arch', help="Arch this bug occurs on")
-        p.add_option('--severity', help="Bug severity")
-        p.add_option('--priority', help="Bug priority")
-        p.add_option('-u', '--url', help="URL for further bug info")
-        p.add_option('--cc',
-                metavar='CC[, CC, ...]', action="append",
-                help="add emails to initial CC list")
-        p.add_option('--blocked',
-                metavar='BUGID[, BUGID, ...]', action="append",
-                help="add bug_ids blocked by this bug")
-        p.add_option('--dependson',
-                metavar='BUGID[, BUGID, ...]', action="append",
-                help="add bug_ids that this bug depends on")
-        p.add_option('--groups',
-                metavar='GROUP[, GROUP, ...]', action="append",
-                help="add groups to which bug is visible")
-        p.add_option('--assigned_to',
-                help='Assign bugzilla to specified email address')
-        p.add_option('--qa_contact',
-                help='Set QA contact to specified email address')
-        p.add_option('--keywords',
-                metavar='KEYWORD[, KEYWORD, ...]', action="append",
-                help="Set specified keywords on new bugzilla")
-        p.add_option('--alias',
-                help='An alias (name) for the bug (must be unique)')
-
-    elif action == 'query':
-        p.set_description("List bug reports that match the given criteria.")
-        # General bug metadata
-        p.add_option('-b', '--bug_id', default=None,
-                help="specify individual bugs by IDs, separated with commas")
-        p.add_option('-p', '--product',
-                help="product name, comma-separated "
-                     "(list with 'bugzilla info --products')")
-        p.add_option('-v', '--version',
-                help="product version, comma-separated")
-        p.add_option('-c', '--component',
-                help="component name(s), comma-separated "
-                     "(list with 'bugzilla info --components PRODUCT')")
-        p.add_option("--sub-component", action="append",
-            help="Sub component. Can be specified multiple times")
-        p.add_option('--components_file', default=None,
-                help="list of component names from a file, one component "
-                     "per line (list with 'bugzilla info -c PRODUCT')")
-        p.add_option('-l', '--long_desc',
-                help="search inside bug comments")
-        p.add_option('-m', '--target_milestone',
-                help="search for a target milestone")
-        p.add_option('-s', '--short_desc',
-                help="search bug summaries")
-        p.add_option('-t', '--bug_status', default="ALL",
-                help="comma-separated list of bug statuses to accept "
-                     "[Default:all]")
-        p.add_option('-x', '--bug_severity', '--severity',
-                help="search severities, comma-separated")
-        p.add_option('-z', '--priority',
-                help="search priorities, comma-separated")
-
-        # Email
-        malg = optparse.OptionGroup(p, "Email Options")
-        malg.add_option('-E', '--emailtype', default="substring",
-                help="Email: specify searching option for emails, "
-                     "ie. substring, notsubstring, exact, ... "
-                     "[Default: substring]")
-        malg.add_option('-o', '--cc',
-                help="Email: search cc lists for given address")
-        malg.add_option('-r', '--reporter',
-                help="Email: search reporter email for given address")
-        malg.add_option('-a', '--assigned_to',
-                help="Email: search for bugs assigned to this address")
-        malg.add_option('-q', '--qa_contact',
-                help="Email: search for bugs which have QA Contact "
-                     "assigned to this address")
-        p.add_option_group(malg)
-
-        # Strings
-        stro = optparse.OptionGroup(p, "String search options")
-        stro.add_option('-u', '--url',
-                help="search keywords field for given url")
-        stro.add_option('-U', '--url_type',
-                help="specify searching option for urls, "
-                     "ie. anywords, allwords, nowords")
-        stro.add_option('-k', '--keywords',
-                help="search keywords field for specified words")
-        stro.add_option('-K', '--keywords_type',
-                help="specify searching option for keywords, "
-                     "ie. anywords, allwords, nowords")
-        stro.add_option('-w', '--status_whiteboard',
-                help="search Status Whiteboard field for specified words")
-        stro.add_option('-W', '--status_whiteboard_type',
-                help="specify searching option for Status Whiteboard, "
-                     "ie. anywords, allwords, nowords")
-        stro.add_option("--tags", help="Search bug 'tags' field")
-        p.add_option_group(stro)
-
-        # Precomposed queries
-        p.add_option('--from-url',
-            help="Use the query given by a query.cgi URL. (Use quotes!)")
-        p.add_option('--quicksearch',
-            help="Search using bugzilla's quicksearch functionality.")
-        p.add_option('--savedsearch',
-            help="Name of a bugzilla saved search. If you don't own this "
-                "saved search, you must passed --savedsearch_sharer_id.")
-        p.add_option('--savedsearch-sharer-id',
-            help="Owner ID of the --savedsearch. You can get this ID from "
-                "the URL bugzilla generates when running the saved search "
-                "from the web UI.")
-
-        # Boolean Charts
-        bgrp = optparse.OptionGroup(p, "Boolean options")
-        bgrp.add_option('-B', '--booleantype', default="substring",
-                help="specify searching option for booleans, ie. substring, "
-                     "notsubstring, exact, ... [Default: substring]")
-        bgrp.add_option('--boolean_query', action="append",
-                help="Create your own query. Format: "
-                     "BooleanName-Condition-Parameter &/| ... . ie, "
-                     "keywords-substring-Partner & "
-                     "keywords-notsubstring-OtherQA")
-        bgrp.add_option('--blocked', action="append",
-                help="Search for bugs that block this bug ID")
-        bgrp.add_option('--dependson', action="append",
-                help="Search for bugs that depend on this bug ID")
-        bgrp.add_option('--flag', action='append',
-                help="Search for bugs that have certain "
-                     "flag states present. Ex --flags=dev_ack+")
-        bgrp.add_option('--qa_whiteboard', action="append",
-                help="search for bugs that have certain QA "
-                     "Whiteboard text present")
-        bgrp.add_option('--devel_whiteboard', action="append",
-                help="search for bugs that have certain "
-                     "Devel Whiteboard text present")
-        bgrp.add_option('--alias', action="append",
-                help="search for bugs that have the provided alias")
-        bgrp.add_option('--fixed_in', action="append",
-                help="search Status Whiteboard field for specified words")
-        p.add_option_group(bgrp)
-
-    elif action == 'info':
-        p.set_description("Get information about the bugzilla server.")
-        p.add_option('-p', '--products', action='store_true',
-                help='Get a list of products')
-        p.add_option('-c', '--components', metavar="PRODUCT",
-                help='List the components in the given product')
-        p.add_option('-o', '--component_owners', metavar="PRODUCT",
-                help='List components (and their owners)')
-        p.add_option('-v', '--versions', metavar="VERSION",
-                help='List the versions for the given product')
-
-    elif action == 'modify':
-        p.set_usage("%prog modify [options] BUGID [BUGID...]")
-        p.set_description("Modify one or more bugs.")
-
-        bgrp = optparse.OptionGroup(p, "Bug details")
-        bgrp.add_option('--product',
-                help="Reassign bug to different product")
-        bgrp.add_option('-c', '--component',
-                help="Reassign bug to different component")
-        bgrp.add_option("--sub-component",
-            help="Reassign bug to different sub-component (rhbz extension)")
-        bgrp.add_option("-v", '--version',
-                help="Reassign bug to different version")
-        bgrp.add_option('-o', '--os',
-                help="Change operating system this bug occurs on")
-        bgrp.add_option('-a', '--arch',
-                help="Change arch this bug occurs on")
-        bgrp.add_option('-u', '--url',
-                help="URL for further bug info")
-        bgrp.add_option('--alias',
-                help='An alias (name) for the bug (must be unique)')
-        p.add_option_group(bgrp)
-
-        sgrp = optparse.OptionGroup(p, "Bug status options")
-        sgrp.add_option('-s', '--status',
-                help='Change status of bug')
-        sgrp.add_option('-k', '--close', metavar="RESOLUTION",
-                help='Close with the given resolution')
-        sgrp.add_option('-d', '--dupeid', metavar="ORIGINAL",
-                help='ID of original bug (implies -k DUPLICATE)')
-        sgrp.add_option('-F', '--fixed_in', metavar="VERSION",
-                help='"Fixed in version" field')
-        p.add_option_group(sgrp)
-
-        cgrp = optparse.OptionGroup(p, "Comment options")
-        cgrp.add_option('-l', '--comment',
-                help='Add a comment')
-        cgrp.add_option('-p', '--private', action='store_true', default=False,
-                help='Mark new comment as private')
-        cgrp.add_option("--summary", help="Change bug summary")
-        p.add_option_group(cgrp)
-
-        egrp = optparse.OptionGroup(p, "Contact options")
-        egrp.add_option('--assignee',
-                help='Assign bugzilla to assignee')
-        egrp.add_option('--cc', action='append', metavar="EMAIL",
-                help='Alter CC list. EMAIL appends, -EMAIL removes.')
-        egrp.add_option('--qa_contact',
-                help='Change QA contact')
-        egrp.add_option('--reset-assignee', action="store_true",
-                help='Reset assignee to component default')
-        egrp.add_option('--reset-qa-contact', action="store_true",
-                help='Reset QA contact to component default')
-        egrp.add_option('--groups', metavar='GROUP[, GROUP, ...]',
-                action="append",
-                help="add groups to which bug is visible")
-        p.add_option_group(egrp)
-
-        tgrp = optparse.OptionGroup(p, "Tracking options")
-        tgrp.add_option('-f', '--flag', action='append',
-                help='Update bugzilla flags with requested type, '
-                     'ie fedora-cvs?, or needinfoX to clear '
-                     '(Use a new option for each flag)')
-        tgrp.add_option('--severity', help="Change bug severity")
-        tgrp.add_option('--priority', help="Change bug priority")
-        tgrp.add_option('--target_milestone', help="Set target milestone")
-        tgrp.add_option('--target_release', help="Set target release")
-        tgrp.add_option('--blocked',
-                metavar='BUGID[, BUGID, ...]', action="append",
-                help="Add bug_ids blocked by this bug. BUGID appends, "
-                     "-BUGID removes, =BUGID overwrites")
-        tgrp.add_option('--dependson', metavar='BUGID[, BUGID, ...]',
-                action="append",
-                help=('Alter depends_on list.  BUGID appends, '
-                     '-BUGID removes, =BUGID overwrites'))
-        tgrp.add_option('--keywords',
-                metavar='KEYWORD', action="append",
-                help="Alter bug keywords list. KEYWORD appends, "
-                     "-KEYWORD removes, =KEYWORD overwrites")
-        tgrp.add_option("", "--whiteboard", metavar="TEXT", action="append",
-                help='Alter status whiteboard text. '
-                      'TEXT appends, -TEXT removes, =TEXT overwrites')
-        tgrp.add_option("--devel_whiteboard",
-                metavar="TEXT", action="append",
-                help='Alter devel whiteboard text. '
-                      'TEXT appends, -TEXT removes, =TEXT overwrites')
-        tgrp.add_option("--internal_whiteboard",
-                metavar="TEXT", action="append",
-                help='Alter internal whiteboard text. '
-                      'TEXT appends, -TEXT removes, =TEXT overwrites')
-        tgrp.add_option("--qa_whiteboard",
-                metavar="TEXT", action="append",
-                help='Alter QA whiteboard. '
-                      'TEXT appends, -TEXT removes, =TEXT overwrites')
-        tgrp.add_option("--tags", metavar="TEXT", action="append",
-                help="Alter bug 'tags' field"
-                     "TEXT appends, -TEXT removes")
-        p.add_option_group(tgrp)
-
-
-    elif action == 'attach':
-        p.set_usage('''
-  %prog attach --file=FILE --desc=DESC [--type=TYPE] BUGID [BUGID...]
-  %prog attach --get=ATTACHID --getall=BUGID [...]
-  %prog attach --type=TYPE BUGID [BUGID...]''')
-        p.set_description("Attach files or download attachments.")
-        p.add_option('-f', '--file', metavar="FILENAME",
-                help='File to attach, or filename for data provided on stdin')
-        p.add_option('-d', '--description', metavar="DESCRIPTION", dest='desc',
-                help="A short description of the file being attached")
-        p.add_option('-t', '--type', metavar="MIMETYPE",
-                help="Mime-type for the file being attached")
-        p.add_option('-g', '--get', metavar="ATTACHID", action="append",
-                default=[], help="Download the attachment with the given ID")
-        p.add_option("--getall", "--get-all", metavar="BUGID", action="append",
-                default=[], help="Download all attachments on the given bug")
-
-    elif action == 'login':
-        p.set_usage('%prog login [username [password]]')
-        p.set_description(
-            "Log into bugzilla and save a login cookie or token.")
-
-    if action in ['new', 'query']:
-        outg = optparse.OptionGroup(p, "Output format options")
-        outg.add_option('-f', '--full', action='store_const', dest='output',
-                const='full', default='normal',
-                help="output detailed bug info")
-        outg.add_option('-i', '--ids', action='store_const', dest='output',
-                const='ids', help="output only bug IDs")
-        outg.add_option('-e', '--extra', action='store_const',
-                dest='output', const='extra',
-                help="output additional bug information "
-                     "(keywords, Whiteboards, etc.)")
-        outg.add_option('--oneline', action='store_const', dest='output',
-                const='oneline',
-                help="one line summary of the bug (useful for scripts)")
-        outg.add_option('--raw', action='store_const', dest='output',
-                const='raw', help="raw output of the bugzilla contents")
-        outg.add_option('--outputformat',
-                help="Print output in the form given. "
-                     "You can use RPM-style tags that match bug "
-                     "fields, e.g.: '%{id}: %{summary}'. See the man page "
-                     "section 'OUTPUT FORMAT' for more details.")
-        p.add_option_group(outg)
-
-    if action in ['new', 'query', 'modify']:
-        message = {
-            'new': 'Set a specified field.',
-            'query': 'Query a specified field.',
-            'modify': 'Modify a specified field.'
-        }.get(action)
-        p.add_option('--field', help="%s FIELD is expected to be \
-                     the raw name used by the bugzilla instance. No safety \
-                     checks are perfomed when using this option." % (message),
-                     action="append", type="str", dest="fields",
-                     metavar="FIELD=VALUE")
-
+def _parser_add_output_options(p):
+    outg = p.add_argument_group("Output format options")
+    outg.add_argument('--full', action='store_const', dest='output',
+            const='full', default='normal',
+            help="output detailed bug info")
+    outg.add_argument('-i', '--ids', action='store_const', dest='output',
+            const='ids', help="output only bug IDs")
+    outg.add_argument('-e', '--extra', action='store_const',
+            dest='output', const='extra',
+            help="output additional bug information "
+                 "(keywords, Whiteboards, etc.)")
+    outg.add_argument('--oneline', action='store_const', dest='output',
+            const='oneline',
+            help="one line summary of the bug (useful for scripts)")
+    outg.add_argument('--raw', action='store_const', dest='output',
+            const='raw', help="raw output of the bugzilla contents")
+    outg.add_argument('--outputformat',
+            help="Print output in the form given. "
+                 "You can use RPM-style tags that match bug "
+                 "fields, e.g.: '%%{id}: %%{summary}'. See the man page "
+                 "section 'Output options' for more details.")
+
+
+def _parser_add_bz_fields(rootp, command):
+    cmd_new = (command == "new")
+    cmd_query = (command == "query")
+    cmd_modify = (command == "modify")
+    if cmd_new:
+        comment_help = "Set initial bug comment/description"
+    elif cmd_query:
+        comment_help = "Search all bug comments"
+    else:
+        comment_help = "Add new bug comment"
+
+    p = rootp.add_argument_group("Standard bugzilla options")
+
+    p.add_argument('-p', '--product', help="Product name")
+    p.add_argument('-v', '--version', help="Product version")
+    p.add_argument('-c', '--component', help="Component name")
+    p.add_argument('-t', '--summary', '--short_desc', help="Bug summary")
+    p.add_argument('-l', '--comment', '--long_desc', help=comment_help)
+    p.add_argument("--sub-component", action="append",
+        help="RHBZ sub component field")
+    p.add_argument('-o', '--os', help="Operating system")
+    p.add_argument('--arch', help="Arch this bug occurs on")
+    p.add_argument('-x', '--severity', help="Bug severity")
+    p.add_argument('-z', '--priority', help="Bug priority")
+    p.add_argument('--alias', help='Bug alias (name)')
+    p.add_argument('-s', '--status', '--bug_status',
+        help='Bug status (NEW, ASSIGNED, etc.)')
+    p.add_argument('-u', '--url', help="URL field")
+    p.add_argument('-m', '--target_milestone', help="Target milestone")
+    p.add_argument('--target_release', help="RHBZ Target release")
+
+    p.add_argument('--blocked', action="append",
+        help="Bug IDs that this bug blocks")
+    p.add_argument('--dependson', action="append",
+        help="Bug IDs that this bug depends on")
+    p.add_argument('--keywords', action="append",
+        help="Bug keywords")
+    p.add_argument('--groups', action="append",
+        help="Which user groups can view this bug")
+
+    p.add_argument('--cc', action="append", help="CC list")
+    p.add_argument('-a', '--assigned_to', '--assignee', help="Bug assignee")
+    p.add_argument('-q', '--qa_contact', help='QA contact')
+
+    if not cmd_new:
+        p.add_argument('-f', '--flag', action='append',
+            help="Bug flags state. Ex:\n"
+                 "  --flag needinfo?\n"
+                 "  --flag dev_ack+")
+        p.add_argument("--tags", action="append", help="Tags field.")
+
+        p.add_argument('-w', "--whiteboard", '--status_whiteboard',
+            action="append", help='Whiteboard field')
+        p.add_argument("--devel_whiteboard", action="append",
+            help='RHBZ devel whiteboard field')
+        p.add_argument("--internal_whiteboard", action="append",
+            help='RHBZ internal whiteboard field')
+        p.add_argument("--qa_whiteboard", action="append",
+            help='RHBZ QA whiteboard field')
+        p.add_argument('-F', '--fixed_in',
+            help="RHBZ 'Fixed in version' field")
+
+    # Put this at the end, so it sticks out more
+    p.add_argument('--field',
+        metavar="FIELD=VALUE", action="append", dest="fields",
+        help="Manually specify a bugzilla XMLRPC field. FIELD is "
+        "the raw name used by the bugzilla instance. For example if your "
+        "bugzilla instance has a custom field cf_my_field, do:\n"
+        "  --field cf_my_field=VALUE")
 
     # Used by unit tests, not for end user consumption
-    if action in ['new', 'query', 'modify']:
-        p.add_option('--test-return-result', action="store_true",
-                     help=optparse.SUPPRESS_HELP)
+    p.add_argument('--test-return-result', action="store_true",
+        help=argparse.SUPPRESS)
+
+    if not cmd_modify:
+        _parser_add_output_options(rootp)
+
+
+def _setup_action_new_parser(subparsers):
+    description = ("Create a new bug report. "
+        "--product, --component, --version, --summary, and --comment "
+        "must be specified. "
+        "Options that take multiple values accept comma separated lists, "
+        "including --cc, --blocks, --dependson, --groups, and --keywords.")
+    p = subparsers.add_parser("new", description=description)
+
+    _parser_add_bz_fields(p, "new")
+
+
+def _setup_action_query_parser(subparsers):
+    description = ("List bug reports that match the given criteria. "
+        "Certain options can accept a comma separated list to query multiple "
+        "values, including --status, --component, --product, --version, --id.")
+    epilog = ("Note: querying via explicit command line options will only "
+        "get you so far. See the --from-url option for a way to use powerful "
+        "Web UI queries from the command line.")
+    p = subparsers.add_parser("query",
+        description=description, epilog=epilog)
+
+    _parser_add_bz_fields(p, "query")
+
+    g = p.add_argument_group("'query' specific options")
+    g.add_argument('-b', '--id', '--bug_id',
+        help="specify individual bugs by IDs, separated with commas")
+    g.add_argument('-r', '--reporter',
+        help="Email: search reporter email for given address")
+    g.add_argument('--quicksearch',
+        help="Search using bugzilla's quicksearch functionality.")
+    g.add_argument('--savedsearch',
+        help="Name of a bugzilla saved search. If you don't own this "
+            "saved search, you must passed --savedsearch_sharer_id.")
+    g.add_argument('--savedsearch-sharer-id',
+        help="Owner ID of the --savedsearch. You can get this ID from "
+            "the URL bugzilla generates when running the saved search "
+            "from the web UI.")
+
+    # Keep this at the end so it sticks out more
+    g.add_argument('--from-url', metavar="WEB_QUERY_URL",
+        help="Make a working query via bugzilla's 'Advanced search' web UI, "
+             "grab the url from your browser (the string with query.cgi or "
+             "buglist.cgi in it), and --from-url will run it via the "
+             "bugzilla API. Don't forget to quote the string! "
+             "This only works for Bugzilla 5 and Red Hat bugzilla")
+
+    # Deprecated options
+    p.add_argument('-E', '--emailtype', help=argparse.SUPPRESS)
+    p.add_argument('--components_file', help=argparse.SUPPRESS)
+    p.add_argument('-U', '--url_type',
+            help=argparse.SUPPRESS)
+    p.add_argument('-K', '--keywords_type',
+            help=argparse.SUPPRESS)
+    p.add_argument('-W', '--status_whiteboard_type',
+            help=argparse.SUPPRESS)
+    p.add_argument('-B', '--booleantype',
+            help=argparse.SUPPRESS)
+    p.add_argument('--boolean_query', action="append",
+            help=argparse.SUPPRESS)
+    p.add_argument('--fixed_in_type', help=argparse.SUPPRESS)
+
+
+def _setup_action_info_parser(subparsers):
+    description = ("List products or component information about the "
+        "bugzilla server.")
+    p = subparsers.add_parser("info", description=description)
+
+    p.add_argument('-p', '--products', action='store_true',
+            help='Get a list of products')
+    p.add_argument('-c', '--components', metavar="PRODUCT",
+            help='List the components in the given product')
+    p.add_argument('-o', '--component_owners', metavar="PRODUCT",
+            help='List components (and their owners)')
+    p.add_argument('-v', '--versions', metavar="VERSION",
+            help='List the versions for the given product')
+
+
+def _setup_action_modify_parser(subparsers):
+    usage = ("bugzilla modify [options] BUGID [BUGID...]\n"
+        "Fields that take multiple values have a special input format.\n"
+        "Append:    --cc=foo at example.com\n"
+        "Overwrite: --cc==foo at example.com\n"
+        "Remove:    --cc=-foo at example.com\n"
+        "Options that accept this format: --cc, --blocked, --dependson,\n"
+        "    --groups, --tags, whiteboard fields.")
+    p = subparsers.add_parser("modify", usage=usage)
+
+    _parser_add_bz_fields(p, "modify")
+
+    g = p.add_argument_group("'modify' specific options")
+    g.add_argument('-k', '--close', metavar="RESOLUTION",
+        help='Close with the given resolution (WONTFIX, NOTABUG, etc.)')
+    g.add_argument('-d', '--dupeid', metavar="ORIGINAL",
+        help='ID of original bug. Implies --close DUPLICATE')
+    g.add_argument('--private', action='store_true', default=False,
+        help='Mark new comment as private')
+    g.add_argument('--reset-assignee', action="store_true",
+        help='Reset assignee to component default')
+    g.add_argument('--reset-qa-contact', action="store_true",
+        help='Reset QA contact to component default')
+
+
+def _setup_action_attach_parser(subparsers):
+    usage = """
+bugzilla attach --file=FILE --desc=DESC [--type=TYPE] BUGID [BUGID...]
+bugzilla attach --get=ATTACHID --getall=BUGID [...]
+bugzilla attach --type=TYPE BUGID [BUGID...]"""
+    description = "Attach files or download attachments."
+    p = subparsers.add_parser("attach", description=description, usage=usage)
+
+    p.add_argument('-f', '--file', metavar="FILENAME",
+            help='File to attach, or filename for data provided on stdin')
+    p.add_argument('-d', '--description', '--summary',
+            metavar="SUMMARY", dest='desc',
+            help="A short summary of the file being attached")
+    p.add_argument('-t', '--type', metavar="MIMETYPE",
+            help="Mime-type for the file being attached")
+    p.add_argument('-g', '--get', metavar="ATTACHID", action="append",
+            default=[], help="Download the attachment with the given ID")
+    p.add_argument("--getall", "--get-all", metavar="BUGID", action="append",
+            default=[], help="Download all attachments on the given bug")
+
+
+def _setup_action_login_parser(subparsers):
+    usage = 'bugzilla login [username [password]]'
+    description = "Log into bugzilla and save a login cookie or token."
+    subparsers.add_parser("login", description=description, usage=usage)
 
-    return p
+
+def setup_parser():
+    rootparser = _setup_root_parser()
+    subparsers = rootparser.add_subparsers(dest="command_name")
+    _setup_action_new_parser(subparsers)
+    _setup_action_query_parser(subparsers)
+    _setup_action_info_parser(subparsers)
+    _setup_action_modify_parser(subparsers)
+    _setup_action_attach_parser(subparsers)
+    _setup_action_login_parser(subparsers)
+    return rootparser
 
 
 ####################
 # Command routines #
 ####################
 
-def generate_man_page():
-    from logilab.common.optik_ext import ManHelpFormatter
-    import datetime
-
-    today = datetime.date.today()
-    datestr = today.strftime("%B %d, %Y")
-
-    # pylint: disable=W1401
-    # Anomalous backslash in string, man format confuses pylint
-    manpage = \
-'''.TH bugzilla 1  "%s" "version %s" "User Commands"
-.SH NAME
-bugzilla \- command-line interface to Bugzilla over XML-RPC
-.SH SYNOPSIS
-.B bugzilla
-[\\fIoptions\\fR] [\\fIcommand\\fR] [\\fIcommand-options\\fR]
-.SH DESCRIPTION
-.PP
-.BR bugzilla
-is a command-line utility that allows access to the XML-RPC interface provided
-by Bugzilla.
-.PP
-\\fIcommand\\fP is one of:
-.br
-.I \\fR * login - log into the given bugzilla instance
-.br
-.I \\fR * new - create a new bug
-.br
-.I \\fR * query - search for bugs matching given criteria
-.br
-.I \\fR * modify - modify existing bugs
-.br
-.I \\fR * attach - attach files to existing bugs, or get attachments
-.br
-.I \\fR * info - get info about the given bugzilla instance
-''' % (datestr, bugzilla.__version__)
-
-    manformatter = ManHelpFormatter()
-    parser = setup_parser()
-    parser.formatter = manformatter
-
-    opt_section = parser.format_option_help()
-    manpage += opt_section.replace("OPTIONS", "GLOBAL OPTIONS")
-    for action in cmdlist:
-        action_parser = setup_action_parser(action)
-        action_parser.remove_option("--help")
-        action_parser.formatter = manformatter
-        opt_section = action_parser.format_option_help()
-        manpage += opt_section.replace("OPTIONS",
-                                       '\[oq]%s\[cq] OPTIONS' % action.upper())
-    manpage += \
... 6184 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-bugzilla.git



More information about the Python-modules-commits mailing list