summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYaakov Nemoy <loupgaroublond@gmail.com>2008-10-01 19:50:34 -0400
committerYaakov M. Nemoy <loupgaroublond@gmail.com>2008-10-01 19:50:34 -0400
commitcfb2820e1051de15e37c4a3d12be9b5514f81610 (patch)
tree45f5706906db6ee17542da263ebf79b9695a6228
parent7810e072debc0255de3135874e5c46f156f52d4a (diff)
downloadfedora-devshell-cfb2820e1051de15e37c4a3d12be9b5514f81610.tar.gz
fedora-devshell-cfb2820e1051de15e37c4a3d12be9b5514f81610.tar.xz
fedora-devshell-cfb2820e1051de15e37c4a3d12be9b5514f81610.zip
Breaks everything up into seperate files.
I had a problem where having Module in the local namespace was not the same as having Module in the non local namespace (via an import). Somehow breaking it down this way seemed simpler.
-rw-r--r--base/__init__.py0
-rw-r--r--base/base.py216
-rw-r--r--base/exceptions.py4
-rw-r--r--base/module.py4
-rw-r--r--base/vars.py10
-rwxr-xr-xdevshell.py213
-rw-r--r--modules/audit.py6
-rw-r--r--modules/bugs.py4
-rw-r--r--modules/mail.py7
-rw-r--r--modules/pkg.py9
-rwxr-xr-xports.py5
11 files changed, 255 insertions, 223 deletions
diff --git a/base/__init__.py b/base/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/base/__init__.py
diff --git a/base/base.py b/base/base.py
new file mode 100644
index 0000000..214d1d5
--- /dev/null
+++ b/base/base.py
@@ -0,0 +1,216 @@
+import logging
+import os
+
+from inspect import isclass
+from collections import deque
+from os.path import join
+
+
+from module import Module
+from vars import __description__, __version__, header, prompt
+
+
+log = logging.getLogger('devshell')
+modules = {}
+
+def print_docstrings(module=None):
+ """
+ Print out the docstrings for all methods in the specified module.
+ If no module is specified, then display docstrings for all modules.
+
+ Arguments:
+ module: an object subclassing Module (optional)
+ """
+ def _print_docstrings(name, module):
+ log.info(header(name))
+ for prop in filter(lambda x: x[0] != '_', dir(module)):
+ if callable(getattr(module, prop)) and hasattr(module, '__doc__') \
+ and getattr(module, prop).__doc__:
+ log.info(" |- [%s] %s" % (prop,
+ getattr(module, prop).__doc__.strip()))
+ if not module:
+ for name, module in modules.items():
+ _print_docstrings(name, module)
+ else:
+ _print_docstrings(str(module.__class__).split('.')[-1], module)
+
+def load_modules():
+ global modules
+ log.debug("Loading modules")
+ #TODO: better way to find modules
+ for f in os.listdir(os.path.abspath('modules')):
+ module_name, ext = os.path.splitext(f)
+ if ext == '.py':
+ exec "from modules import %s as module" % module_name
+ for item in dir(module):
+ obj = getattr(module, item)
+ if item[0] != '_' and isclass(obj):
+ log.debug('%s is subclass of Module: %s' %\
+ (obj, issubclass(obj, Module)))
+ if item[0] != '_' and isclass(obj) and issubclass(obj, Module) \
+ and obj is not Module:
+ modules[item.lower()] = obj
+ log.info(" * %s" % item)
+ del module
+
+def load_module(name, data=[]):
+ top = None
+ try:
+ log.debug("Loading %s.__init__(%s)" % (name, data))
+ top = modules[name](*data)
+ except TypeError, e:
+ log.debug('got type error')
+ log.error("%s: %s" % (name, e))
+ raise ModuleError('probably bad call to __init__' , e)
+ return top
+
+def shell():
+ while True:
+ try:
+ data = raw_input('/'.join(shell.prompt) + '> ')
+ except (EOFError, KeyboardInterrupt):
+ print
+ break
+ if not data: continue
+ if data in ('quit', 'exit'): break
+ keyword = data.split()[0]
+ args = data.split()[1:]
+
+ # Show the docstrings to all methods for all loaded modules
+ if keyword == 'help':
+ print_docstrings()
+
+ # Go up a module in our stack
+ elif keyword in ('up', 'cd..', 'cd ..'):
+ shell.stack = shell.stack[:-1]
+ shell.prompt = shell.prompt[:-1]
+
+ # Show the docstrings for all methods in our current module
+ elif keyword in ('ls', 'help', '?'):
+ if len(shell.stack):
+ print_docstrings(shell.stack[-1])
+ else:
+ print_docstrings()
+
+ # Flush our module stack
+ elif keyword == 'cd':
+ shell.stack = []
+ shell.prompt = prompt
+
+ # iPython. Never leave home without it.
+ elif keyword in ('py', 'python'):
+ os.system("ipython -noconfirm_exit")
+ else:
+ #figure out if there is a top
+ if len(shell.stack):
+ top = shell.stack[-1]
+ else:
+ top = None
+ output, top, params = do_command(data.split(), top)
+ if top:
+ shell.stack += [top]
+ shell.prompt += [top.__class__.__name__] + params
+shell.stack = []
+shell.prompt = prompt
+
+def do_command(data, top=None):
+
+ # Do some intelligent handling of unknown input.
+ # For the given input 'foo bar', we first check if we have the
+ # module 'foo' loaded, then we push it on the top of our module
+ # stack and check if it has the 'bar' attribute. If so, we call
+ # it with any remaining arguments
+ data = deque(data)
+ log.debug(data)
+ params = []
+
+ module = None
+ while len(data):
+ if not top:
+ log.debug('not top')
+ mod = data.popleft()
+ try:
+ module = modules[mod]
+ except KeyError, e:
+ log.error('%s is not a known module' % e.message)
+ return None, None, None
+ log.debug('mod is %s' % mod)
+ params = []
+ while len(data):
+ log.debug('params so far %s' % params)
+ log.debug('inner loop %s' % data)
+ param = data.popleft()
+ if hasattr(module, param):
+ data.appendleft(param)
+ break
+ params += [param]
+ try:
+ top = module = load_module(mod, params)
+ mod_params = params
+ loaded_module = True
+ except ModuleError, e:
+ log.debug(e.reason)
+ break
+ else:
+ log.debug('is top')
+ params = []
+ log.debug('params so far %s' % params)
+ param = data.popleft()
+ if hasattr(top, param):
+ log.debug("next property %s found in %s" % (param, top))
+ top = getattr(top, param)
+ else:
+ log.debug("adding argument: %s" % param)
+ params += [param]
+ output = None
+ if len(params):
+ output = top(*params)
+
+ if module:
+ return output, module, mod_params
+ else:
+ return output, None, None
+
+def setup_options():
+ '''Sets up an options parser for all command line utilities
+
+ Arguements:
+ none: none!
+
+ Return Values:
+ opts: an object containing the options specified
+ args: remaining arguments
+ '''
+ from optparse import OptionParser
+ parser = OptionParser(usage="%prog [options]",
+ version="%s %s" % ('%prog', __version__),
+ description=__description__)
+ parser.add_option('-v', '--verbose', action='store_true', dest='verbose',
+ help='Display verbose debugging output')
+ return parser.parse_args()
+
+def setup_logger(opts):
+ '''Configures the logger system to the environment
+
+ Arguments:
+ opts: options from an OptionParser
+
+ Return Values:
+ none: none!
+ '''
+ global log
+ # Setup our logger
+ sh = logging.StreamHandler()
+ if opts.verbose:
+ log.setLevel(logging.DEBUG)
+ sh.setLevel(logging.DEBUG)
+ format = logging.Formatter("[%(levelname)s] %(message)s")
+ else:
+ log.setLevel(logging.INFO)
+ sh.setLevel(logging.INFO)
+ format = logging.Formatter("%(message)s")
+ sh.setFormatter(format)
+ log.addHandler(sh)
+
+__all__ = ['do_command', 'log', 'setup_options', 'load_module', 'shell',
+ 'print_docstrings', 'modules', 'setup_logger', 'load_modules'] \ No newline at end of file
diff --git a/base/exceptions.py b/base/exceptions.py
new file mode 100644
index 0000000..471dd0e
--- /dev/null
+++ b/base/exceptions.py
@@ -0,0 +1,4 @@
+class ModuleError(Exception):
+ def __init__(self, reason, error):
+ self.reason = reason
+ self.error = error
diff --git a/base/module.py b/base/module.py
new file mode 100644
index 0000000..d527ea0
--- /dev/null
+++ b/base/module.py
@@ -0,0 +1,4 @@
+
+class Module(object):
+ """ Our parent class for all command modules """
+ pass
diff --git a/base/vars.py b/base/vars.py
new file mode 100644
index 0000000..232432b
--- /dev/null
+++ b/base/vars.py
@@ -0,0 +1,10 @@
+from os.path import join, expanduser
+
+__version__ = '0.0.1'
+__description__ = 'A shell for hacking on the Fedora project'
+
+FEDORA_DIR = join(expanduser('~'), 'code', 'fedora')
+DEVSHELL_DIR = join(expanduser('~'), '.devshell')
+
+header = lambda x: "%s %s %s" % ('=' * 2, x, '=' * (76 - len(x)))
+prompt = ['\033[34;1mfedora\033[0m'] \ No newline at end of file
diff --git a/devshell.py b/devshell.py
index 05bf215..786ec41 100755
--- a/devshell.py
+++ b/devshell.py
@@ -31,218 +31,9 @@
# - audit <project> (flawfinder/rats/etc)
import os
-import re
-import stat
-import gzip
-import email
-import urllib2
-import logging
-import commands
-from glob import glob
-from os.path import expanduser, exists, join, dirname, isdir
-from mailbox import UnixMailbox
-from datetime import datetime, timedelta
-
-__version__ = '0.0.1'
-__description__ = 'A shell for hacking on the Fedora project'
-
-FEDORA_DIR = join(expanduser('~'), 'code', 'fedora')
-DEVSHELL_DIR = join(expanduser('~'), '.devshell')
-
-stack = []
-prompt = ['\033[34;1mfedora\033[0m']
-modules = {}
-header = lambda x: "%s %s %s" % ('=' * 2, x, '=' * (76 - len(x)))
-log = logging.getLogger(__name__)
-
-class Module:
- """ Our parent class for all command modules """
- pass
-
-def load_modules():
- global modules
- from inspect import isclass
- log.debug("Loading modules")
- for f in os.listdir(os.path.abspath('modules')):
- module_name, ext = os.path.splitext(f)
- if ext == '.py':
- exec "from modules import %s as module" % module_name
- for item in dir(module):
- obj = getattr(module, item)
- if item[0] != '_' and isclass(obj):
- modules[item.lower()] = obj
- log.info(" * %s" % item)
- del module
-
-def print_docstrings(module=None):
- """
- Print out the docstrings for all methods in the specified module.
- If no module is specified, then display docstrings for all modules.
- """
- def _print_docstrings(name, module):
- log.info(header(name))
- for prop in filter(lambda x: x[0] != '_', dir(module)):
- if callable(getattr(module, prop)) and hasattr(module, '__doc__') \
- and getattr(module, prop).__doc__:
- log.info(" |- [%s] %s" % (prop,
- getattr(module, prop).__doc__.strip()))
- if not module:
- for name, module in modules.items():
- _print_docstrings(name, module)
- else:
- _print_docstrings(str(module.__class__).split('.')[-1], module)
-
-def shell():
- global stack, prompt
- while True:
- try:
- data = raw_input('/'.join(prompt) + '> ')
- except (EOFError, KeyboardInterrupt):
- print
- break
- if not data: continue
- if data in ('quit', 'exit'): break
- keyword = data.split()[0]
- args = data.split()[1:]
-
- # Show the docstrings to all methods for all loaded modules
- if keyword == 'help':
- print_docstrings()
-
- # Go up a module in our stack
- elif keyword in ('up', 'cd..', 'cd ..'):
- stack = stack[:-1]
- prompt = prompt[:-1]
-
- # Show the docstrings for all methods in our current module
- elif keyword in ('ls', 'help', '?'):
- if len(stack):
- print_docstrings(stack[-1])
- else:
- print_docstrings()
-
- # Flush our module stack
- elif keyword == 'cd':
- stack = []
- prompt = ['\033[34;1mfedora\033[0m']
-
- # iPython. Never leave home without it.
- elif keyword in ('py', 'python'):
- os.system("ipython -noconfirm_exit")
- else:
- #figure out if there is a top
- if len(stack):
- top = stack[-1]
- else:
- top = None
- output, top, params = do_command(data.split(), top)
- stack += [top]
- prompt += [top.__class__.__name__] + params
-
-class ModuleError(Exception):
- def __init__(self, reason, error):
- self.reason = reason
- self.error = error
-
-def load_module(name, data=[]):
-# stack = []
-# prompt = []
- top = None
- try:
- log.debug("Loading %s.__init__(%s)" % (name, data))
- top = modules[name](*data)
-# stack += [top]
-# prompt += [name] + data
- except TypeError, e:
- log.debug('got type error')
- log.error("%s: %s" % (name, e))
- raise ModuleError('probably bad call to __init__' , e)
- return top
-
-
-def do_command(data, top=None):
-
- # Do some intelligent handling of unknown input.
- # For the given input 'foo bar', we first check if we have the
- # module 'foo' loaded, then we push it on the top of our module
- # stack and check if it has the 'bar' attribute. If so, we call
- # it with any remaining arguments
- from collections import deque
- data = deque(data)
- log.debug(data)
- params = []
-
- module = None
- while len(data):
- if not top:
- log.debug('not top')
- mod = data.popleft()
- try:
- module = modules[mod]
- except KeyError, e:
- log.error('%s is not a known module' % e.message)
- return None, None, None
- log.debug('mod is %s' % mod)
- params = []
- while len(data):
- log.debug('params so far %s' % params)
- log.debug('inner loop %s' % data)
- param = data.popleft()
- if hasattr(module, param):
- data.appendleft(param)
- break
- params += [param]
- try:
- top = module = load_module(mod, params)
- mod_params = params
- loaded_module = True
- except ModuleError, e:
- log.debug(e.reason)
- break
- else:
- log.debug('is top')
- params = []
- log.debug('params so far %s' % params)
- param = data.popleft()
- if hasattr(top, param):
- log.debug("next property %s found in %s" % (param, top))
- top = getattr(top, param)
- else:
- log.debug("adding argument: %s" % param)
- params += [param]
- output = None
- if len(params):
- output = top(*params)
-
- if module:
- return output, module, mod_params
- else:
- return output, None, None
-
-def setup_options():
- from optparse import OptionParser
- parser = OptionParser(usage="%prog [options]",
- version="%s %s" % ('%prog', __version__),
- description=__description__)
- parser.add_option('-v', '--verbose', action='store_true', dest='verbose',
- help='Display verbose debugging output')
- return parser.parse_args()
-
-def setup_logger(opts):
- global log
- # Setup our logger
- sh = logging.StreamHandler()
- if opts.verbose:
- log.setLevel(logging.DEBUG)
- sh.setLevel(logging.DEBUG)
- format = logging.Formatter("[%(levelname)s] %(message)s")
- else:
- log.setLevel(logging.INFO)
- sh.setLevel(logging.INFO)
- format = logging.Formatter("%(message)s")
- sh.setFormatter(format)
- log.addHandler(sh)
+from base.base import load_modules, shell, setup_logger, setup_options, log
+from base.vars import FEDORA_DIR
def main():
(opts, args) = setup_options()
diff --git a/modules/audit.py b/modules/audit.py
index 5e89f53..fccd494 100644
--- a/modules/audit.py
+++ b/modules/audit.py
@@ -1,9 +1,11 @@
+from base.module import Module
-
-class Audit:
+class Audit(Module):
""" Perform various code audits on a specified Pkg """
tools = ['flawfinder', 'rats']
def __init__(self, pkg):
""" @param pkg: a Pkg instance """
+
+__all__ = ['Audit']
diff --git a/modules/bugs.py b/modules/bugs.py
index 359a06e..19dbb70 100644
--- a/modules/bugs.py
+++ b/modules/bugs.py
@@ -1,6 +1,7 @@
import os
+from base.module import Module
-class Bugs:
+class Bugs(Module):
"""
Interface for doing useful things with Bugs.
TODO: add support for arbitrary bug trackers!
@@ -22,3 +23,4 @@ class Bugs:
"""
os.system('firefox "https://bugzilla.redhat.com/buglist.cgi?query_format=specific&order=bugs.bug_id&bug_status=__open__&product=&content=%s"' % text)
+__all__ = ['Bugs'] \ No newline at end of file
diff --git a/modules/mail.py b/modules/mail.py
index 790845d..9a2532a 100644
--- a/modules/mail.py
+++ b/modules/mail.py
@@ -10,11 +10,12 @@ from os.path import join, exists, dirname, isdir
from mailbox import UnixMailbox
from datetime import datetime, timedelta
-from devshell import DEVSHELL_DIR
+from base.vars import DEVSHELL_DIR
+from base.module import Module
log = logging.getLogger(__name__)
-class Mail:
+class Mail(Module):
""" A module for searching/viewing mailing lists """
url = 'https://www.redhat.com/archives/%s/%s'
@@ -114,3 +115,5 @@ class Mail:
log.info("To: %s" % msg['To'])
log.info("Subject: %s" % msg['Subject'])
log.info('\n'.join(self.__body(msg)))
+
+__all__ = ['Mail'] \ No newline at end of file
diff --git a/modules/pkg.py b/modules/pkg.py
index a748b92..d586795 100644
--- a/modules/pkg.py
+++ b/modules/pkg.py
@@ -2,7 +2,8 @@ import os
import commands
from os.path import isdir, join
-from devshell import FEDORA_DIR
+from base.vars import FEDORA_DIR
+from base.module import Module
# Hack-filled at the moment.
@@ -24,10 +25,10 @@ class CannotFindPackage(Exception):
pass
#FIXME: use this?
-class SCM:
+class SCM(object):
cmds = dict(update='update', clone='clone', log='log', diff='diff')
-class Package(object):
+class Source(Module):
def __init__(self, name, branch='devel'):
self.name = name
@@ -130,3 +131,5 @@ class Package(object):
def bugs(self):
raise NotImplementedError
+
+__all__ = ['Source'] \ No newline at end of file
diff --git a/ports.py b/ports.py
index f455221..3534b83 100755
--- a/ports.py
+++ b/ports.py
@@ -17,11 +17,8 @@
# Authors: Yaakov M. Nemoy <ynemoy@redhat.com>
#
-import sys
-import os
-from devshell import *
+from base.base import setup_options, load_modules, log, do_command
-print sys.argv
def main():
(opts, args) = setup_options()