Updated commands to use the new objectdb.search API.

This commit is contained in:
Griatch 2013-05-11 23:22:02 +02:00
parent 218e4a149c
commit 78e7346962
11 changed files with 97 additions and 84 deletions

View file

@ -7,7 +7,6 @@ Admin commands
import time, re import time, re
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User from django.contrib.auth.models import User
from src.players.models import PlayerDB
from src.server.sessionhandler import SESSIONS from src.server.sessionhandler import SESSIONS
from src.server.models import ServerConfig from src.server.models import ServerConfig
from src.utils import utils, prettytable, search from src.utils import utils, prettytable, search
@ -92,7 +91,6 @@ class CmdBoot(MuxCommand):
feedback += "\nReason given: %s" % reason feedback += "\nReason given: %s" % reason
for session in boot_list: for session in boot_list:
name = session.uname
session.msg(feedback) session.msg(feedback)
pobj.disconnect_session_from_player(session.sessid) pobj.disconnect_session_from_player(session.sessid)
@ -287,12 +285,7 @@ class CmdDelPlayer(MuxCommand):
# We use player_search since we want to be sure to find also players # We use player_search since we want to be sure to find also players
# that lack characters. # that lack characters.
players = caller.search("*%s" % args) players = caller.search_player(args, quiet=True)
if not players:
try:
players = PlayerDB.objects.filter(id=args)
except ValueError:
pass
if not players: if not players:
# try to find a user instead of a Player # try to find a user instead of a Player
@ -337,7 +330,6 @@ class CmdDelPlayer(MuxCommand):
player = players player = players
user = player.user user = player.user
character = player.character
if not player.access(caller, 'delete'): if not player.access(caller, 'delete'):
string = "You don't have the permissions to delete that player." string = "You don't have the permissions to delete that player."
@ -346,17 +338,14 @@ class CmdDelPlayer(MuxCommand):
uname = user.username uname = user.username
# boot the player then delete # boot the player then delete
if character and character.has_player: self.msg("Informing and disconnecting player ...")
self.msg("Booting and informing player ...") string = "\nYour account '%s' is being *permanently* deleted.\n" % uname
string = "\nYour account '%s' is being *permanently* deleted.\n" % uname if reason:
if reason: string += " Reason given:\n '%s'" % reason
string += " Reason given:\n '%s'" % reason player.unpuppet_all()
character.msg(string) for session in SESSIONS.sessions_from_player(player):
# we have a bootable object with a connected player player.msg(string, sessid=session.sessid)
sessions = SESSIONS.sessions_from_player(character.player) player.disconnect_session_from_player(session.sessid)
for session in sessions:
session.msg(string)
session.disconnect()
user.delete() user.delete()
player.delete() player.delete()
self.msg("Player %s was successfully deleted." % uname) self.msg("Player %s was successfully deleted." % uname)
@ -466,7 +455,7 @@ class CmdNewPassword(MuxCommand):
return return
# the player search also matches 'me' etc. # the player search also matches 'me' etc.
player = caller.search("*%s" % self.lhs, global_search=True, player=True) player = caller.search_player(self.lhs)
if not player: if not player:
return return
player.user.set_password(self.rhs) player.user.set_password(self.rhs)
@ -510,8 +499,10 @@ class CmdPerm(MuxCommand):
playermode = 'player' in self.switches or lhs.startswith('*') playermode = 'player' in self.switches or lhs.startswith('*')
# locate the object if playermode:
obj = caller.search(lhs, global_search=True, player=playermode) obj = caller.search_player(lhs)
else:
obj = caller.search(lhs, global_search=True)
if not obj: if not obj:
return return

View file

@ -499,9 +499,9 @@ class CmdDestroy(MuxCommand):
def delobj(objname, byref=False): def delobj(objname, byref=False):
# helper function for deleting a single object # helper function for deleting a single object
string = "" string = ""
obj = caller.search(objname, global_dbref=byref) obj = caller.search(objname)
if not obj: if not obj:
self.caller.msg(" (Objects to destroy must either be local or specified with a unique dbref.)") self.caller.msg(" (Objects to destroy must either be local or specified with a unique #dbref.)")
return "" return ""
if not "override" in self.switches and obj.dbid == int(settings.CHARACTER_DEFAULT_HOME.lstrip("#")): if not "override" in self.switches and obj.dbid == int(settings.CHARACTER_DEFAULT_HOME.lstrip("#")):
return "\nYou are trying to delete CHARACTER_DEFAULT_HOME. If you want to do this, use the /override switch." return "\nYou are trying to delete CHARACTER_DEFAULT_HOME. If you want to do this, use the /override switch."
@ -1018,7 +1018,7 @@ class CmdOpen(ObjManipCommand):
# check if this exit object already exists at the location. # check if this exit object already exists at the location.
# we need to ignore errors (so no automatic feedback)since we # we need to ignore errors (so no automatic feedback)since we
# have to know the result of the search to decide what to do. # have to know the result of the search to decide what to do.
exit_obj = caller.search(exit_name, location=location, ignore_errors=True) exit_obj = caller.search(exit_name, location=location, quiet=True)
if len(exit_obj) > 1: if len(exit_obj) > 1:
# give error message and return # give error message and return
caller.search(exit_name, location=location) caller.search(exit_name, location=location)
@ -1681,8 +1681,10 @@ class CmdExamine(ObjManipCommand):
self.player_mode = "player" in self.switches or obj_name.startswith('*') self.player_mode = "player" in self.switches or obj_name.startswith('*')
if self.player_mode:
obj = caller.search(obj_name, player=self.player_mode, global_dbref=True) obj = self.search_player(obj_name)
else:
obj = caller.search(obj_name)
if not obj: if not obj:
continue continue

View file

@ -271,7 +271,7 @@ class CmdDrop(MuxCommand):
# Because the DROP command by definition looks for items # Because the DROP command by definition looks for items
# in inventory, call the search function using location = caller # in inventory, call the search function using location = caller
results = caller.search(self.args, location=caller, ignore_errors=True) results = caller.search(self.args, location=caller, quiet=True)
# now we send it into the error handler (this will output consistent # now we send it into the error handler (this will output consistent
# error messages if there are problems). # error messages if there are problems).

View file

@ -182,7 +182,6 @@ class CmdSetHelp(MuxCommand):
def func(self): def func(self):
"Implement the function" "Implement the function"
caller = self.caller
switches = self.switches switches = self.switches
lhslist = self.lhslist lhslist = self.lhslist

View file

@ -390,7 +390,7 @@ class CmdWho(MuxPlayerCommand):
plr_pobject = plr_pobject or session.get_player() plr_pobject = plr_pobject or session.get_player()
table.add_row([utils.crop(plr_pobject.name, width=25), table.add_row([utils.crop(plr_pobject.name, width=25),
utils.time.format(delta_conn, 0), utils.time.format(delta_conn, 0),
utils,time_format(delta_cmd, 1)]) utils.time_format(delta_cmd, 1)])
string = "{wPlayers:{n\n%s\n%s unique accounts logged in." % (table, nplayers==1 and "One player" or nplayers) string = "{wPlayers:{n\n%s\n%s unique accounts logged in." % (table, nplayers==1 and "One player" or nplayers)
self.msg(string) self.msg(string)
@ -561,8 +561,6 @@ class CmdColorTest(MuxPlayerCommand):
def func(self): def func(self):
"Show color tables" "Show color tables"
player = self.caller
if self.args.startswith("a"): if self.args.startswith("a"):
# show ansi 16-color table # show ansi 16-color table
from src.utils import ansi from src.utils import ansi

View file

@ -7,7 +7,6 @@ System commands
import traceback import traceback
import os, datetime, time import os, datetime, time
from time import time as timemeasure from time import time as timemeasure
from sys import getsizeof
import sys import sys
import django, twisted import django, twisted

View file

@ -212,7 +212,7 @@ class ObjectManager(TypedObjectManager):
# main search methods and helper functions # main search methods and helper functions
@returns_typeclass_list @returns_typeclass_list
def object_search(self, ostring=None, def object_search(self, ostring,
attribute_name=None, attribute_name=None,
typeclass=None, typeclass=None,
candidates=None, candidates=None,
@ -268,7 +268,7 @@ class ObjectManager(TypedObjectManager):
if candidates: if candidates:
# Convenience check to make sure candidates are really dbobjs # Convenience check to make sure candidates are really dbobjs
candidates = [cand.dbobj for cand in make_iter(candidates) if _GA(cand, "_hasattr")(cand, "dbobj")] candidates = [cand.dbobj for cand in make_iter(candidates) if cand]
if typeclass: if typeclass:
candidates = [cand for cand in candidates if _GA(cand, "db_typeclass_path") in typeclass] candidates = [cand for cand in candidates if _GA(cand, "db_typeclass_path") in typeclass]

View file

@ -25,6 +25,7 @@ from src.server.caches import get_prop_cache, set_prop_cache, del_prop_cache
from src.typeclasses.typeclass import TypeClass from src.typeclasses.typeclass import TypeClass
from src.players.models import PlayerNick from src.players.models import PlayerNick
from src.objects.manager import ObjectManager from src.objects.manager import ObjectManager
from src.players.models import PlayerDB
from src.commands.cmdsethandler import CmdSetHandler from src.commands.cmdsethandler import CmdSetHandler
from src.commands import cmdhandler from src.commands import cmdhandler
from src.scripts.scripthandler import ScriptHandler from src.scripts.scripthandler import ScriptHandler
@ -569,8 +570,8 @@ class ObjectDB(TypedObject):
<num>-<string> - can be used to differentiate between multiple same-named matches <num>-<string> - can be used to differentiate between multiple same-named matches
global_search (bool): Search all objects globally. This is overruled by "location" keyword. global_search (bool): Search all objects globally. This is overruled by "location" keyword.
use_nicks (bool): Use nickname-replace (nicktype "object") on the search string use_nicks (bool): Use nickname-replace (nicktype "object") on the search string
typeclass (str or Typeclass): Limit search only to Objects with this typeclass. May be a list of typeclasses typeclass (str or Typeclass, or list of either): Limit search only to Objects with this typeclass. May
for a broader search. be a list of typeclasses for a broader search.
location (Object): Specify a location to search, if different from the self's given location location (Object): Specify a location to search, if different from the self's given location
plus its contents. This can also be a list of locations. plus its contents. This can also be a list of locations.
attribute_name (str): Use this named Attribute to match ostring against, instead of object.key. attribute_name (str): Use this named Attribute to match ostring against, instead of object.key.
@ -598,7 +599,7 @@ class ObjectDB(TypedObject):
# handle some common self-references: # handle some common self-references:
if ostring == _HERE: if ostring == _HERE:
return self.location return self.location
if ostring in (_ME, _SELF, '*' + _ME, '*' + _SELF): if ostring in (_ME, _SELF):
return self return self
if use_nicks: if use_nicks:
@ -633,15 +634,25 @@ class ObjectDB(TypedObject):
# db manager expects database objects # db manager expects database objects
candidates = [obj.dbobj for obj in candidates] candidates = [obj.dbobj for obj in candidates]
results = ObjectDB.objects.object_search(ostring=ostring, results = ObjectDB.objects.object_search(ostring,
typeclass=typeclass,
attribute_name=attribute_name, attribute_name=attribute_name,
typeclass=typeclass,
candidates=candidates, candidates=candidates,
exact=exact) exact=exact)
if quiet: if quiet:
return results return results
return _AT_SEARCH_RESULT(self, ostring, results, global_search) return _AT_SEARCH_RESULT(self, ostring, results, global_search)
def search_player(self, ostring, quiet=False):
"""
Simple wrapper of the player search also handling me, self
"""
if ostring in (_ME, _SELF) and _GA(self, "db_player"):
return _GA(self, "db_player")
results = PlayerDB.objects.player_search(ostring)
if quiet:
return results
return _AT_SEARCH_RESULT(self, ostring, results, True)
# #
# Execution/action methods # Execution/action methods

View file

@ -143,58 +143,63 @@ class Object(TypeClass):
def search(self, ostring, def search(self, ostring,
global_search=False, global_search=False,
global_dbref=False,
attribute_name=None,
use_nicks=False, use_nicks=False,
typeclass=None,
location=None, location=None,
ignore_errors=False, attribute_name=None,
player=False): quiet=False,
exact=False):
""" """
Returns the typeclass of an Object matching a search string/condition
Perform a standard object search in the database, handling Perform a standard object search in the database, handling
multiple results and lack thereof gracefully. multiple results and lack thereof gracefully. By default, only
objects in self's current location or inventory is searched.
Note: to find Players, use eg. ev.player_search.
ostring: (str) The string to match object names against. Inputs:
Obs - To find a player, append * to the
start of ostring.
global_search(bool): Search all objects, not just the current
location/inventory
attribute_name (string) Which attribute to match
(if None, uses default 'name')
use_nicks (bool) : Use nickname replace (off by default)
location (Object): If None, use caller's current location
ignore_errors (bool): Don't display any error messages even
if there are none/multiple matches -
just return the result as a list.
player (Objectt): Don't search for an Object but a Player.
This will also find players that don't
currently have a character.
Returns - a unique Object/Player match or None. All error ostring (str): Primary search criterion. Will be matched against object.key (with object.aliases second)
messages are handled by system-commands and the parser-handlers unless the keyword attribute_name specifies otherwise. Special strings:
specified in settings. #<num> - search by unique dbref. This is always a global search.
me,self - self-reference to this object
<num>-<string> - can be used to differentiate between multiple same-named matches
global_search (bool): Search all objects globally. This is overruled by "location" keyword.
use_nicks (bool): Use nickname-replace (nicktype "object") on the search string
typeclass (str or Typeclass): Limit search only to Objects with this typeclass. May be a list of typeclasses
for a broader search.
location (Object): Specify a location to search, if different from the self's given location
plus its contents. This can also be a list of locations.
attribute_name (str): Use this named Attribute to match ostring against, instead of object.key.
quiet (bool) - don't display default error messages - return multiple matches as a list and
no matches as None. If not set (default), will echo error messages and return None.
exact (bool) - if unset (default) - prefers to match to beginning of string rather than not matching
at all. If set, requires exact mathing of entire string.
Use *<string> to search for objects controlled by a specific Returns:
player. Note that the object controlled by the player will be
returned, not the player object itself. This also means that quiet=False (default):
this will not find Players without a character. Use the keyword no match or multimatch:
player=True to find player objects. auto-echoes errors to self.msg, then returns None
(results are handled by modules set by settings.SEARCH_AT_RESULT
and settings.SEARCH_AT_MULTIMATCH_INPUT)
match:
a unique object match
quiet=True:
no match or multimatch:
returns None or list of multi-matches
match:
a unique object match
Note - for multiple matches, the engine accepts a number
linked to the key in order to separate the matches from
each other without showing the dbref explicitly. Default
syntax for this is 'N-searchword'. So for example, if there
are three objects in the room all named 'ball', you could
address the individual ball as '1-ball', '2-ball', '3-ball'
etc.
""" """
return self.dbobj.search(ostring, return self.dbobj.search(ostring,
global_search=global_search, global_search=global_search,
global_dbref=global_dbref, use_nicks=use_nicks,
attribute_name=attribute_name, typeclass=typeclass,
use_nicks=use_nicks, location=location,
location=location, attribute_name=attribute_name,
ignore_errors=ignore_errors, quiet=quiet,
player=player) exact=quiet)
def execute_cmd(self, raw_string, sessid=None): def execute_cmd(self, raw_string, sessid=None):
""" """

View file

@ -160,7 +160,6 @@ class PlayerManager(TypedObjectManager):
ostring = a string or database id. ostring = a string or database id.
""" """
ostring = ostring.lstrip("*")
dbref = self.dbref(ostring) dbref = self.dbref(ostring)
if dbref or dbref == 0: if dbref or dbref == 0:
matches = self.filter(id=dbref) matches = self.filter(id=dbref)

View file

@ -39,8 +39,13 @@ from src.commands import cmdhandler
from src.utils import logger, utils from src.utils import logger, utils
from src.utils.utils import inherits_from, make_iter from src.utils.utils import inherits_from, make_iter
from django.utils.translation import ugettext as _
__all__ = ("PlayerAttribute", "PlayerNick", "PlayerDB") __all__ = ("PlayerAttribute", "PlayerNick", "PlayerDB")
_ME = _("me")
_SELF = _("self")
_SESSIONS = None _SESSIONS = None
_AT_SEARCH_RESULT = utils.variable_from_module(*settings.SEARCH_AT_RESULT.rsplit('.', 1)) _AT_SEARCH_RESULT = utils.variable_from_module(*settings.SEARCH_AT_RESULT.rsplit('.', 1))
_MULTISESSION_MODE = settings.MULTISESSION_MODE _MULTISESSION_MODE = settings.MULTISESSION_MODE
@ -556,6 +561,10 @@ class PlayerDB(TypedObject):
Extra keywords are ignored, but are allowed in call in order to make API more consistent Extra keywords are ignored, but are allowed in call in order to make API more consistent
with objects.models.TypedObject.search. with objects.models.TypedObject.search.
""" """
# handle me, self
if ostring in (_ME, _SELF, '*' + _ME, '*' + _SELF):
return self
matches = _GA(self, "__class__").objects.player_search(ostring) matches = _GA(self, "__class__").objects.player_search(ostring)
matches = _AT_SEARCH_RESULT(self, ostring, matches, global_search=True) matches = _AT_SEARCH_RESULT(self, ostring, matches, global_search=True)
if matches and return_character: if matches and return_character: