Went over the Command class' basic methods, cleaning up and optimizing while still trying to keep things clean, such as using cleverer loops and try...except instead of if statements. Also cleaned up the way attributes are retrieved. Results in roughly a halving of the time that the code spends in the command.py module.

This commit is contained in:
Griatch 2012-02-06 00:59:41 +01:00
parent 7b2a4e4467
commit d36a79b2cc
3 changed files with 27 additions and 46 deletions

View file

@ -50,8 +50,7 @@ def union(cmdset_a, cmdset_b, duplicates=False):
if duplicates and cmdset_a.priority == cmdset_b.priority: if duplicates and cmdset_a.priority == cmdset_b.priority:
cmdset_c.commands.extend(cmdset_b.commands) cmdset_c.commands.extend(cmdset_b.commands)
else: else:
cmdset_c.commands.extend([cmd for cmd in cmdset_b cmdset_c.commands.extend([cmd for cmd in cmdset_b if not cmd in cmdset_a])
if not cmd in cmdset_a])
return cmdset_c return cmdset_c
def intersect(cmdset_a, cmdset_b, duplicates=False): def intersect(cmdset_a, cmdset_b, duplicates=False):
@ -83,14 +82,11 @@ def instantiate(cmd):
and not, say a cmdclass. If it is, instantiate it. and not, say a cmdclass. If it is, instantiate it.
Other types, like strings, are passed through. Other types, like strings, are passed through.
""" """
if callable(cmd): try:
# this is a valid check since Command *instances*
# don't implement __call__, so this will catch
# Command *classes* and instantiate them.
return cmd() return cmd()
except TypeError:
return cmd return cmd
class CmdSet(object): class CmdSet(object):
""" """
This class describes a unique cmdset that understands priorities. CmdSets This class describes a unique cmdset that understands priorities. CmdSets
@ -223,11 +219,9 @@ class CmdSet(object):
""" """
if inherits_from(cmd, "src.commands.cmdset.CmdSet"): if inherits_from(cmd, "src.commands.cmdset.CmdSet"):
# this is a command set so merge all commands in that set # cmd is a command set so merge all commands in that set
# to this one. We are not protecting against recursive # to this one. We raise a visible error if we created
# loops (adding a cmdset that itself adds this cmdset here # an infinite loop (adding cmdset to itself somehow)
# since such an error will be very visible and lead to a
# traceback at startup anyway.
try: try:
cmd = instantiate(cmd) cmd = instantiate(cmd)
except RuntimeError, e: except RuntimeError, e:
@ -258,8 +252,7 @@ class CmdSet(object):
cmd can be either a cmd instance or a key string. cmd can be either a cmd instance or a key string.
""" """
cmd = instantiate(cmd) cmd = instantiate(cmd)
self.commands = [oldcmd for oldcmd in self.commands self.commands = [oldcmd for oldcmd in self.commands if oldcmd != cmd]
if oldcmd != cmd]
def get(self, cmd): def get(self, cmd):
""" """
@ -268,7 +261,6 @@ class CmdSet(object):
a key string. a key string.
""" """
cmd = instantiate(cmd) cmd = instantiate(cmd)
if cmd:
for thiscmd in self.commands: for thiscmd in self.commands:
if thiscmd == cmd: if thiscmd == cmd:
return thiscmd return thiscmd
@ -283,8 +275,7 @@ class CmdSet(object):
commands starting with double underscore __. commands starting with double underscore __.
These are excempt from merge operations. These are excempt from merge operations.
""" """
return [cmd for cmd in self.commands return [cmd for cmd in self.commands if cmd.key.startswith('__')]
if len(cmd.key) > 2 and cmd.key[:2] == '__']
def copy_this(self): def copy_this(self):
""" """
@ -300,7 +291,7 @@ class CmdSet(object):
cmdset.mergetype = self.mergetype cmdset.mergetype = self.mergetype
cmdset.priority = self.priority cmdset.priority = self.priority
cmdset.duplicates = self.duplicates cmdset.duplicates = self.duplicates
cmdset.key_mergetypes = copy.deepcopy(self.key_mergetypes) cmdset.key_mergetypes = self.key_mergetypes.copy() #copy.deepcopy(self.key_mergetypes)
return cmdset return cmdset
def make_unique(self, caller): def make_unique(self, caller):
@ -367,8 +358,7 @@ class CmdSet(object):
if self.priority >= cmdset_b.priority: if self.priority >= cmdset_b.priority:
# A higher or equal priority than B # A higher or equal priority than B
mergetype = self.key_mergetypes.get(cmdset_b.key, mergetype = self.key_mergetypes.get(cmdset_b.key, self.mergetype)
self.mergetype)
if mergetype == "Intersect": if mergetype == "Intersect":
cmdset_c = intersect(self, cmdset_b, cmdset_b.duplicates) cmdset_c = intersect(self, cmdset_b, cmdset_b.duplicates)
elif mergetype == "Replace": elif mergetype == "Replace":
@ -379,8 +369,7 @@ class CmdSet(object):
cmdset_c = union(self, cmdset_b, cmdset_b.duplicates) cmdset_c = union(self, cmdset_b, cmdset_b.duplicates)
else: else:
# B higher priority than A # B higher priority than A
mergetype = cmdset_b.key_mergetypes.get(self.key, mergetype = cmdset_b.key_mergetypes.get(self.key, cmdset_b.mergetype)
cmdset_b.mergetype)
if mergetype == "Intersect": if mergetype == "Intersect":
cmdset_c = intersect(cmdset_b, self, self.duplicates) cmdset_c = intersect(cmdset_b, self, self.duplicates)
elif mergetype == "Replace": elif mergetype == "Replace":
@ -396,7 +385,6 @@ class CmdSet(object):
cmdset_c.actual_mergetype = mergetype cmdset_c.actual_mergetype = mergetype
# return the system commands to the cmdset # return the system commands to the cmdset
for cmd in sys_commands: cmdset_c.add(sys_commands)
cmdset_c.add(cmd)
return cmdset_c return cmdset_c

View file

@ -105,9 +105,10 @@ class Command(object):
key and aliases. key and aliases.
input can be either a cmd object or the name of a command. input can be either a cmd object or the name of a command.
""" """
if type(cmd) != self: try:
return self.match(cmd)
return self.match(cmd.key) return self.match(cmd.key)
except AttributeError: # got a string
return self.match(cmd)
def __contains__(self, query): def __contains__(self, query):
""" """
@ -117,10 +118,11 @@ class Command(object):
input can be either a command object or a command name. input can be either a command object or a command name.
""" """
if type(query) == type(Command()): try:
query = query.key query = query.key
return (query in self.key) or \ except AttributeError: # we got a string
(sum([query in alias for alias in self.aliases]) > 0) pass
return (query in self.key) or any(query in alias for alias in self.aliases)
def match(self, cmdname): def match(self, cmdname):
""" """

View file

@ -24,15 +24,6 @@ def is_iter(iterable):
""" """
return hasattr(iterable, '__iter__') return hasattr(iterable, '__iter__')
# if isinstance(iterable, basestring):
# # skip all forms of strings (str, unicode etc)
# return False
# try:
# # check if object implements iter protocol
# return iter(iterable)
# except TypeError:
# return False
def fill(text, width=78, indent=0): def fill(text, width=78, indent=0):
""" """
Safely wrap text to a certain number of characters. Safely wrap text to a certain number of characters.
@ -396,7 +387,7 @@ def inherits_from(obj, parent):
parent_path = "%s.%s" % (parent.__module__, parent.__name__) parent_path = "%s.%s" % (parent.__module__, parent.__name__)
else: else:
parent_path = "%s.%s" % (parent.__class__.__module__, parent.__class__.__name__) parent_path = "%s.%s" % (parent.__class__.__module__, parent.__class__.__name__)
return any(True for obj_path in obj_paths if obj_path == parent_path) return any(1 for obj_path in obj_paths if obj_path == parent_path)
def format_table(table, extra_space=1): def format_table(table, extra_space=1):