* implement command dictionary using metaclasses
* automatically implement short command names by this: try pisi-cli svn it *.pisi
This commit is contained in:
@@ -11,3 +11,10 @@
|
|||||||
# pisi.cli package version
|
# pisi.cli package version
|
||||||
__version__ = "0.1"
|
__version__ = "0.1"
|
||||||
|
|
||||||
|
import pisi
|
||||||
|
|
||||||
|
class Error(pisi.Error):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Exception(pisi.Exception):
|
||||||
|
pass
|
||||||
|
|||||||
+121
-97
@@ -14,34 +14,41 @@ import sys
|
|||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
|
|
||||||
import pisi
|
import pisi
|
||||||
|
import pisi.cli
|
||||||
from pisi.uri import URI
|
from pisi.uri import URI
|
||||||
|
|
||||||
|
|
||||||
def commands_string():
|
|
||||||
s = ''
|
|
||||||
list = commands.keys()
|
|
||||||
list.sort()
|
|
||||||
for x in list:
|
|
||||||
s += x + '\n'
|
|
||||||
return s
|
|
||||||
|
|
||||||
|
|
||||||
def get_command(cmd, fail=False):
|
|
||||||
|
|
||||||
if commands.has_key(cmd):
|
|
||||||
obj = commands[cmd]()
|
|
||||||
return obj
|
|
||||||
|
|
||||||
if fail:
|
|
||||||
print "Unrecognized command: ", cmd
|
|
||||||
sys.exit(1)
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
class Command(object):
|
class Command(object):
|
||||||
"""generic help string for any command"""
|
"""generic help string for any command"""
|
||||||
|
|
||||||
|
# class variables
|
||||||
|
|
||||||
|
cmd = []
|
||||||
|
cmd_dict = {}
|
||||||
|
|
||||||
|
def commands_string():
|
||||||
|
s = ''
|
||||||
|
list = [x.name[0] for x in Command.cmd]
|
||||||
|
list.sort()
|
||||||
|
for x in list:
|
||||||
|
s += x + '\n'
|
||||||
|
return s
|
||||||
|
commands_string = staticmethod(commands_string)
|
||||||
|
|
||||||
|
def get_command(cmd, fail=False):
|
||||||
|
|
||||||
|
if Command.cmd_dict.has_key(cmd):
|
||||||
|
return Command.cmd_dict[cmd]()
|
||||||
|
|
||||||
|
if fail:
|
||||||
|
print "Unrecognized command: ", cmd
|
||||||
|
sys.exit(1)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
get_command = staticmethod(get_command)
|
||||||
|
|
||||||
|
# instance variabes
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# now for the real parser
|
# now for the real parser
|
||||||
import pisi
|
import pisi
|
||||||
@@ -124,12 +131,15 @@ class Command(object):
|
|||||||
"""do cleanup work for PiSi components"""
|
"""do cleanup work for PiSi components"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def name(self):
|
#def name(self):
|
||||||
"""(command name, shortname) pair to be filled by subclasses"""
|
# """(command name, shortname) pair to be filled by subclasses"""
|
||||||
pass
|
# pass
|
||||||
|
|
||||||
|
def get_name(self):
|
||||||
|
return self.__class__.longname
|
||||||
|
|
||||||
def format_name(self):
|
def format_name(self):
|
||||||
(name, shortname) = self.name()
|
(name, shortname) = self.get_name()
|
||||||
if shortname:
|
if shortname:
|
||||||
return "%s (%s)" % (name, shortname)
|
return "%s (%s)" % (name, shortname)
|
||||||
else:
|
else:
|
||||||
@@ -147,6 +157,24 @@ class Command(object):
|
|||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
|
||||||
|
|
||||||
|
class autocommand(type):
|
||||||
|
def __init__(cls, name, bases, dict):
|
||||||
|
super(autocommand, cls).__init__(name, bases, dict)
|
||||||
|
Command.cmd.append(cls)
|
||||||
|
name = getattr(cls, 'name', None)
|
||||||
|
if name is None:
|
||||||
|
raise pisi.cli.Error('command lacks name')
|
||||||
|
longname, shortname = name
|
||||||
|
def add_cmd(cmd):
|
||||||
|
if Command.cmd_dict.has_key(cmd):
|
||||||
|
raise pisi.cli.Error('duplicate command %s' % cmd)
|
||||||
|
else:
|
||||||
|
Command.cmd_dict[cmd] = cls
|
||||||
|
add_cmd(longname)
|
||||||
|
if shortname:
|
||||||
|
add_cmd(shortname)
|
||||||
|
|
||||||
|
|
||||||
class Help(Command):
|
class Help(Command):
|
||||||
"""Prints help for given commands.
|
"""Prints help for given commands.
|
||||||
|
|
||||||
@@ -154,14 +182,15 @@ Usage: help [ <command1> <command2> ... <commandn> ]
|
|||||||
|
|
||||||
If run without parameters, it prints the general help."""
|
If run without parameters, it prints the general help."""
|
||||||
|
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
#TODO? Discard Help's own usage doc in favor of general usage doc
|
#TODO? Discard Help's own usage doc in favor of general usage doc
|
||||||
#self.__doc__ = usage_text
|
#self.__doc__ = usage_text
|
||||||
#self.__doc__ += commands_string()
|
#self.__doc__ += commands_string()
|
||||||
super(Help, self).__init__()
|
super(Help, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = ("help", "h")
|
||||||
return ("help", "h")
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if not self.args:
|
if not self.args:
|
||||||
@@ -193,11 +222,12 @@ Usage: build <pspec.xml>
|
|||||||
You can give a URI of the pspec.xml file. PISI will
|
You can give a URI of the pspec.xml file. PISI will
|
||||||
fetch all necessary files and build the package for you.
|
fetch all necessary files and build the package for you.
|
||||||
"""
|
"""
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(Build, self).__init__()
|
super(Build, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = ("build", "bi")
|
||||||
return ("build", "bi")
|
|
||||||
|
|
||||||
def options(self):
|
def options(self):
|
||||||
buildno_opts(self)
|
buildno_opts(self)
|
||||||
@@ -258,11 +288,12 @@ Usage: install <package1> <package2> ... <packagen>
|
|||||||
You may use filenames, URIs or package names for packages. If you have
|
You may use filenames, URIs or package names for packages. If you have
|
||||||
specified a package name, it should exist in a specified repository.
|
specified a package name, it should exist in a specified repository.
|
||||||
"""
|
"""
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(Install, self).__init__()
|
super(Install, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = "install", "it"
|
||||||
return ("install", "it")
|
|
||||||
|
|
||||||
def options(self):
|
def options(self):
|
||||||
super(Install, self).options()
|
super(Install, self).options()
|
||||||
@@ -286,11 +317,12 @@ Usage: Upgrade <package1> <package2> ... <packagen>
|
|||||||
You may use filenames, URIs or package names for packages. If you have
|
You may use filenames, URIs or package names for packages. If you have
|
||||||
specified a package name, it should exist in a specified repository.
|
specified a package name, it should exist in a specified repository.
|
||||||
"""
|
"""
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(Upgrade, self).__init__()
|
super(Upgrade, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = ("upgrade", "up")
|
||||||
return ("upgrade", "up")
|
|
||||||
|
|
||||||
def options(self):
|
def options(self):
|
||||||
super(Upgrade, self).options()
|
super(Upgrade, self).options()
|
||||||
@@ -313,11 +345,12 @@ Usage: remove <package1> <package2> ... <packagen>
|
|||||||
|
|
||||||
Remove package(s) from your system. Just give the package names to remove.
|
Remove package(s) from your system. Just give the package names to remove.
|
||||||
"""
|
"""
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(Remove, self).__init__()
|
super(Remove, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = ("remove", "rm")
|
||||||
return ("remove", "rm")
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if not self.args:
|
if not self.args:
|
||||||
@@ -336,11 +369,12 @@ Usage: Upgrade
|
|||||||
|
|
||||||
Upgrade the entire system.
|
Upgrade the entire system.
|
||||||
"""
|
"""
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(Upgrade, self).__init__()
|
super(Upgrade, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = ("upgrade-all", None)
|
||||||
return ("upgrade-all", None)
|
|
||||||
|
|
||||||
def options(self):
|
def options(self):
|
||||||
super(UpgradeAll, self).options()
|
super(UpgradeAll, self).options()
|
||||||
@@ -360,11 +394,12 @@ class ConfigurePending(PackageOp):
|
|||||||
"""configure pending packages
|
"""configure pending packages
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(ConfigurePending, self).__init__()
|
super(ConfigurePending, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = ("configure-pending", "cp")
|
||||||
return ("configure-pending", "cp")
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
@@ -379,11 +414,12 @@ class Info(Command):
|
|||||||
Usage: info <package1> <package2> ... <packagen>
|
Usage: info <package1> <package2> ... <packagen>
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(Info, self).__init__()
|
super(Info, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = ("info", "i")
|
||||||
return ("info", "i")
|
|
||||||
|
|
||||||
def options(self):
|
def options(self):
|
||||||
self.parser.add_option("-f", "--files", action="store_true",
|
self.parser.add_option("-f", "--files", action="store_true",
|
||||||
@@ -428,11 +464,12 @@ tags from them and accumulates the information in an output XML file,
|
|||||||
named by default 'pisi-index.xml'. In particular, it indexes both
|
named by default 'pisi-index.xml'. In particular, it indexes both
|
||||||
source and binary packages.
|
source and binary packages.
|
||||||
"""
|
"""
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(Index, self).__init__()
|
super(Index, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = ("index", "ix")
|
||||||
return ("index", "ix")
|
|
||||||
|
|
||||||
def options(self):
|
def options(self):
|
||||||
self.parser.add_option("-a", "--absolute-uris", action="store_true",
|
self.parser.add_option("-a", "--absolute-uris", action="store_true",
|
||||||
@@ -461,11 +498,12 @@ Usage: list-installed
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(ListInstalled, self).__init__()
|
super(ListInstalled, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = ("list-installed", "li")
|
||||||
return ("list-installed", "li")
|
|
||||||
|
|
||||||
def options(self):
|
def options(self):
|
||||||
self.parser.add_option("-l", "--long", action="store_true",
|
self.parser.add_option("-l", "--long", action="store_true",
|
||||||
@@ -502,11 +540,12 @@ Usage: update-repo <repo1> <repo2> ... <repon>
|
|||||||
<repoi>: repository name
|
<repoi>: repository name
|
||||||
Synchronizes the PiSi databases with the current repository.
|
Synchronizes the PiSi databases with the current repository.
|
||||||
"""
|
"""
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(UpdateRepo, self).__init__()
|
super(UpdateRepo, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = ("update-repo", "ur")
|
||||||
return ("update-repo", "ur")
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if not self.args:
|
if not self.args:
|
||||||
@@ -529,11 +568,12 @@ Usage: add-repo <repo> <indexuri>
|
|||||||
|
|
||||||
NB: We support only local files (e.g., /a/b/c) and http:// URIs at the moment
|
NB: We support only local files (e.g., /a/b/c) and http:// URIs at the moment
|
||||||
"""
|
"""
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(AddRepo, self).__init__()
|
super(AddRepo, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = ("add-repo", "ar")
|
||||||
return ("add-repo", "ar")
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
@@ -555,11 +595,12 @@ Usage: remove-repo <repo1> <repo2> ... <repon>
|
|||||||
|
|
||||||
Remove all repository information from the system.
|
Remove all repository information from the system.
|
||||||
"""
|
"""
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(RemoveRepo, self).__init__()
|
super(RemoveRepo, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = ("remove-repo", "rr")
|
||||||
return ("remove-repo", "rr")
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
@@ -580,11 +621,12 @@ Usage: list-repo
|
|||||||
|
|
||||||
Lists currently tracked repositories.
|
Lists currently tracked repositories.
|
||||||
"""
|
"""
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(ListRepo, self).__init__()
|
super(ListRepo, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = ("list-repo", "lr")
|
||||||
return ("list-repo", "lr")
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
@@ -603,11 +645,12 @@ Usage: list-available [ <repo1> <repo2> ... repon ]
|
|||||||
|
|
||||||
Gives a brief list of PiSi components published in the repository.
|
Gives a brief list of PiSi components published in the repository.
|
||||||
"""
|
"""
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(ListAvailable, self).__init__()
|
super(ListAvailable, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = ("list-available", "la")
|
||||||
return ("list-available", "li")
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
from pisi.repodb import repodb
|
from pisi.repodb import repodb
|
||||||
@@ -638,11 +681,12 @@ Gives a brief list of PiSi components published in the repository.
|
|||||||
class ListPending(Command):
|
class ListPending(Command):
|
||||||
"""List pending packages"""
|
"""List pending packages"""
|
||||||
|
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(ListPending, self).__init__()
|
super(ListPending, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = ("list-pending", "lp")
|
||||||
return ("list-pending", "lp")
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
from pisi.installdb import installdb
|
from pisi.installdb import installdb
|
||||||
@@ -682,11 +726,12 @@ You can give an URI of the pspec.xml file. PISI will fetch all
|
|||||||
necessary files and unpack the source and prepare a source directory
|
necessary files and unpack the source and prepare a source directory
|
||||||
for you.
|
for you.
|
||||||
"""
|
"""
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(BuildUntil, self).__init__()
|
super(BuildUntil, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = ("build-until", "bu")
|
||||||
return ("build-until", "bu")
|
|
||||||
|
|
||||||
def options(self):
|
def options(self):
|
||||||
self.parser.add_option("-s", action="store", dest="state")
|
self.parser.add_option("-s", action="store", dest="state")
|
||||||
@@ -712,11 +757,12 @@ Usage: build-dounpack <pspec file>
|
|||||||
|
|
||||||
TODO: desc.
|
TODO: desc.
|
||||||
"""
|
"""
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(BuildUnpack, self).__init__()
|
super(BuildUnpack, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = ("build-unpack", "biu")
|
||||||
return ("build-unpack", "biu")
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if not self.args:
|
if not self.args:
|
||||||
@@ -736,11 +782,12 @@ Usage: build-dosetup <pspec file>
|
|||||||
|
|
||||||
TODO: desc.
|
TODO: desc.
|
||||||
"""
|
"""
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(BuildSetup, self).__init__()
|
super(BuildSetup, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = ("build-setup", "bis")
|
||||||
return ("build-setup", "bis")
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if not self.args:
|
if not self.args:
|
||||||
@@ -761,11 +808,12 @@ Usage: build-dobuild <pspec file>
|
|||||||
|
|
||||||
TODO: desc.
|
TODO: desc.
|
||||||
"""
|
"""
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(BuildBuild, self).__init__()
|
super(BuildBuild, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = ("build-dobuild", "bib")
|
||||||
return ("build-dobuild", "bib")
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if not self.args:
|
if not self.args:
|
||||||
@@ -785,11 +833,12 @@ Usage: build-doinstall <pspec file>
|
|||||||
|
|
||||||
TODO: desc.
|
TODO: desc.
|
||||||
"""
|
"""
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(BuildInstall, self).__init__()
|
super(BuildInstall, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = ("build-doinstall", "bii")
|
||||||
return ("build-doinstall", "bii")
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if not self.args:
|
if not self.args:
|
||||||
@@ -810,11 +859,12 @@ Usage: build-dobuild <pspec file>
|
|||||||
|
|
||||||
TODO: desc.
|
TODO: desc.
|
||||||
"""
|
"""
|
||||||
|
__metaclass__ = autocommand
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(BuildPackage, self).__init__()
|
super(BuildPackage, self).__init__()
|
||||||
|
|
||||||
def name(self):
|
name = ("build-dopackage", "bip")
|
||||||
return ("build-dopackage", "bip")
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
if not self.args:
|
if not self.args:
|
||||||
@@ -826,32 +876,6 @@ TODO: desc.
|
|||||||
pisi.toplevel.build_until(arg, "buildpackages", self.authInfo)
|
pisi.toplevel.build_until(arg, "buildpackages", self.authInfo)
|
||||||
self.finalize()
|
self.finalize()
|
||||||
|
|
||||||
# command dictionary
|
|
||||||
|
|
||||||
commands = {"help": Help,
|
|
||||||
"build": Build,
|
|
||||||
"build-until": BuildUntil,
|
|
||||||
"build-unpack": BuildUnpack,
|
|
||||||
"build-setup": BuildSetup,
|
|
||||||
"build-build": BuildBuild,
|
|
||||||
"build-install": BuildInstall,
|
|
||||||
"build-package": BuildPackage,
|
|
||||||
"info": Info,
|
|
||||||
"install": Install,
|
|
||||||
"configure-pending": ConfigurePending,
|
|
||||||
"list-pending": ListPending,
|
|
||||||
"list-installed": ListInstalled,
|
|
||||||
"list-available": ListAvailable,
|
|
||||||
"search-available": SearchAvailable,
|
|
||||||
"remove": Remove,
|
|
||||||
"upgrade": Upgrade,
|
|
||||||
"index": Index,
|
|
||||||
"update-repo": UpdateRepo,
|
|
||||||
"add-repo": AddRepo,
|
|
||||||
"remove-repo": RemoveRepo,
|
|
||||||
"list-repo": ListRepo
|
|
||||||
}
|
|
||||||
|
|
||||||
usage_text1 = """%prog <command> [options] [arguments]
|
usage_text1 = """%prog <command> [options] [arguments]
|
||||||
|
|
||||||
where <command> is one of:
|
where <command> is one of:
|
||||||
@@ -862,4 +886,4 @@ usage_text2 = """
|
|||||||
Use \"%prog help <command>\" for help on a specific command.
|
Use \"%prog help <command>\" for help on a specific command.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
usage_text = (usage_text1 + commands_string() + usage_text2)
|
usage_text = (usage_text1 + Command.commands_string() + usage_text2)
|
||||||
|
|||||||
+1
-1
@@ -52,7 +52,7 @@ class PisiCLI(object):
|
|||||||
self.die()
|
self.die()
|
||||||
cmd = self.parser.rargs[0]
|
cmd = self.parser.rargs[0]
|
||||||
|
|
||||||
self.command = get_command(cmd)
|
self.command = Command.get_command(cmd)
|
||||||
if not self.command:
|
if not self.command:
|
||||||
print "Unrecognized command: ", cmd
|
print "Unrecognized command: ", cmd
|
||||||
self.die()
|
self.die()
|
||||||
|
|||||||
Reference in New Issue
Block a user