def __init__(self): "Initiate to avoid AttributeErrors down the line" self.puppet = None self.player = None self.cmdset_storage_string = "" self.cmdset = LazyLoadHandler(self, "cmdset", cmdsethandler.CmdSetHandler, True)
def __init__(self, **kwargs): """the lockhandler works the same as for objects. optional kwargs will be set as properties on the Command at runtime, overloading evential same-named class properties.""" if kwargs: _init_command(self, **kwargs) self.lockhandler = LazyLoadHandler(self, "lockhandler", LockHandler)
def __init__(self, *args, **kwargs): "Parent must be initiated first" TypedObject.__init__(self, *args, **kwargs) # handlers _SA(self, "cmdset", LazyLoadHandler(self, "cmdset", CmdSetHandler, True)) _SA(self, "scripts", LazyLoadHandler(self, "scripts", ScriptHandler)) _SA(self, "nicks", LazyLoadHandler(self, "nicks", NickHandler))
def __init__(self, senders=None, receivers=None, channels=None, message="", header="", type="", lockstring="", hide_from=None): self.senders = senders and make_iter(senders) or [] self.receivers = receivers and make_iter(receivers) or [] self.channels = channels and make_iter(channels) or [] self.type = type self.header = header self.message = message self.lock_storage = lockstring self.locks = LazyLoadHandler(self, "locks", LockHandler) self.hide_from = hide_from and make_iter(hide_from) or [] self.date_sent = datetime.now()
class TempMsg(object): """ This is a non-persistent object for sending temporary messages that will not be stored. It mimics the "real" Msg object, but don't require sender to be given. """ def __init__(self, senders=None, receivers=None, channels=None, message="", header="", type="", lockstring="", hide_from=None): self.senders = senders and make_iter(senders) or [] self.receivers = receivers and make_iter(receivers) or [] self.channels = channels and make_iter(channels) or [] self.type = type self.header = header self.message = message self.lock_storage = lockstring self.locks = LazyLoadHandler(self, "locks", LockHandler) self.hide_from = hide_from and make_iter(hide_from) or [] self.date_sent = datetime.now() def __str__(self): "This handles what is shown when e.g. printing the message" senders = ",".join(obj.key for obj in self.senders) receivers = ",".join(["[%s]" % obj.key for obj in self.channels] + [obj.key for obj in self.receivers]) return "%s->%s: %s" % (senders, receivers, crop(self.message, width=40)) def remove_sender(self, obj): "Remove a sender or a list of senders" for o in make_iter(obj): try: self.senders.remove(o) except ValueError: pass # nothing to remove def remove_receiver(self, obj): "Remove a sender or a list of senders" for o in make_iter(obj): try: self.senders.remove(o) except ValueError: pass # nothing to remove def access(self, accessing_obj, access_type='read', default=False): "checks lock access" return self.locks.check(accessing_obj, access_type=access_type, default=default)
def at_login(self, player): """ Hook called by sessionhandler when the session becomes authenticated. player - the player associated with the session """ self.player = player self.uid = self.player.id self.uname = self.player.username self.logged_in = True self.conn_time = time.time() self.puid = None self.puppet = None self.cmdset_storage = settings.CMDSET_SESSION # Update account's last login time. self.player.last_login = datetime.now() self.player.save() # add the session-level cmdset self.cmdset = LazyLoadHandler(self, "cmdset", cmdsethandler.CmdSetHandler, True)
class TempMsg(object): """ This is a non-persistent object for sending temporary messages that will not be stored. It mimics the "real" Msg object, but don't require sender to be given. """ def __init__( self, senders=None, receivers=None, channels=None, message="", header="", type="", lockstring="", hide_from=None ): self.senders = senders and make_iter(senders) or [] self.receivers = receivers and make_iter(receivers) or [] self.channels = channels and make_iter(channels) or [] self.type = type self.header = header self.message = message self.lock_storage = lockstring self.locks = LazyLoadHandler(self, "locks", LockHandler) self.hide_from = hide_from and make_iter(hide_from) or [] self.date_sent = datetime.now() def __str__(self): "This handles what is shown when e.g. printing the message" senders = ",".join(obj.key for obj in self.senders) receivers = ",".join(["[%s]" % obj.key for obj in self.channels] + [obj.key for obj in self.receivers]) return "%s->%s: %s" % (senders, receivers, crop(self.message, width=40)) def remove_sender(self, obj): "Remove a sender or a list of senders" for o in make_iter(obj): try: self.senders.remove(o) except ValueError: pass # nothing to remove def remove_receiver(self, obj): "Remove a sender or a list of senders" for o in make_iter(obj): try: self.senders.remove(o) except ValueError: pass # nothing to remove def access(self, accessing_obj, access_type="read", default=False): "checks lock access" return self.locks.check(accessing_obj, access_type=access_type, default=default)
class Command(object): """ Base command Usage: command [args] This is the base command class. Inherit from this to create new commands. The cmdhandler makes the following variables available to the command methods (so you can always assume them to be there): self.caller - the game object calling the command self.cmdstring - the command name used to trigger this command (allows you to know which alias was used, for example) cmd.args - everything supplied to the command following the cmdstring (this is usually what is parsed in self.parse()) cmd.cmdset - the cmdset from which this command was matched (useful only seldomly, notably for help-type commands, to create dynamic help entries and lists) cmd.obj - the object on which this command is defined. If a default command, this is usually the same as caller. The following class properties can/should be defined on your child class: key - identifier for command (e.g. "look") aliases - (optional) list of aliases (e.g. ["l", "loo"]) locks - lock string (default is "cmd:all()") help_category - how to organize this help entry in help system (default is "General") auto_help - defaults to True. Allows for turning off auto-help generation arg_regex - (optional) raw string regex defining how the argument part of the command should look in order to match for this command (e.g. must it be a space between cmdname and arg?) (Note that if auto_help is on, this initial string is also used by the system to create the help entry for the command, so it's a good idea to format it similar to this one) """ # Tie our metaclass, for some convenience cleanup __metaclass__ = CommandMeta # the main way to call this command (e.g. 'look') key = "command" # alternative ways to call the command (e.g. 'l', 'glance', 'examine') aliases = [] # a list of lock definitions on the form # cmd:[NOT] func(args) [ AND|OR][ NOT] func2(args) locks = "" # used by the help system to group commands in lists. help_category = "general" # This allows to turn off auto-help entry creation for individual commands. auto_help = True # auto-set (by Evennia on command instantiation) are: # obj - which object this command is defined on # sessid - which session-id (if any) is responsible for # triggering this command # def __init__(self, **kwargs): """the lockhandler works the same as for objects. optional kwargs will be set as properties on the Command at runtime, overloading evential same-named class properties.""" if kwargs: _init_command(self, **kwargs) self.lockhandler = LazyLoadHandler(self, "lockhandler", LockHandler) def __str__(self): "Print the command" return self.key def __eq__(self, cmd): """ Compare two command instances to each other by matching their key and aliases. input can be either a cmd object or the name of a command. """ try: # first assume input is a command (the most common case) return cmd.key in self._matchset except AttributeError: # probably got a string return cmd in self._matchset def __ne__(self, cmd): """ The logical negation of __eq__. Since this is one of the most called methods in Evennia (along with __eq__) we do some code-duplication here rather than issuing a method-lookup to __eq__. """ try: return not cmd.key in self._matcheset except AttributeError: return not cmd in self._matchset def __contains__(self, query): """ This implements searches like 'if query in cmd'. It's a fuzzy matching used by the help system, returning True if query can be found as a substring of the commands key or its aliases. query (str) - query to match against. Should be lower case. """ return any(query in keyalias for keyalias in self._keyaliases) def match(self, cmdname): """ This is called by the system when searching the available commands, in order to determine if this is the one we wanted. cmdname was previously extracted from the raw string by the system. cmdname (str) is always lowercase when reaching this point. """ return cmdname in self._matchset def access(self, srcobj, access_type="cmd", default=False): """ This hook is called by the cmdhandler to determine if srcobj is allowed to execute this command. It should return a boolean value and is not normally something that need to be changed since it's using the Evennia permission system directly. """ return self.lockhandler.check(srcobj, access_type, default=default) def msg(self, msg="", to_obj=None, from_obj=None, sessid=None, all_sessions=False, **kwargs): """ This is a shortcut instad of calling msg() directly on an object - it will detect if caller is an Object or a Player and also appends self.sessid automatically. msg - text string of message to send to_obj - target object of message. Defaults to self.caller from_obj - source of message. Defaults to to_obj data - optional dictionary of data sessid - supply data only to a unique sessid (normally not used - this is only potentially useful if to_obj is a Player object different from self.caller or self.caller.player) all_sessions (bool) - default is to send only to the session connected to the target object """ from_obj = from_obj or self.caller to_obj = to_obj or from_obj if not sessid: if hasattr(to_obj, "sessid"): # this is the case when to_obj is e.g. a Character sessid = all_sessions and None or to_obj.sessid elif to_obj == self.caller: # this is the case if to_obj is the calling Player sessid = all_sessions and None or self.sessid else: # if to_obj is a different Player, all their sessions # will be notified unless sessid was given specifically sessid = None to_obj.msg(msg, from_obj=from_obj, sessid=sessid, **kwargs) # Common Command hooks def at_pre_cmd(self): """ This hook is called before self.parse() on all commands """ pass def at_post_cmd(self): """ This hook is called after the command has finished executing (after self.func()). """ pass def parse(self): """ Once the cmdhandler has identified this as the command we want, this function is run. If many of your commands have a similar syntax (for example 'cmd arg1 = arg2') you should simply define this once and just let other commands of the same form inherit from this. See the docstring of this module for which object properties are available to use (notably self.args). """ pass def func(self): """ This is the actual executing part of the command. It is called directly after self.parse(). See the docstring of this module for which object properties are available (beyond those set in self.parse()) """ # a simple test command to show the available properties string = "-" * 50 string += "\n{w%s{n - Command variables from evennia:\n" % self.key string += "-" * 50 string += "\nname of cmd (self.key): {w%s{n\n" % self.key string += "cmd aliases (self.aliases): {w%s{n\n" % self.aliases string += "cmd locks (self.locks): {w%s{n\n" % self.locks string += "help category (self.help_category): {w%s{n\n" % self.help_category.capitalize() string += "object calling (self.caller): {w%s{n\n" % self.caller string += "object storing cmdset (self.obj): {w%s{n\n" % self.obj string += "command string given (self.cmdstring): {w%s{n\n" % self.cmdstring # show cmdset.key instead of cmdset to shorten output string += fill( "current cmdset (self.cmdset): {w%s{n\n" % (self.cmdset.key if self.cmdset.key else self.cmdset.__class__) ) self.caller.msg(string)
class ServerSession(Session): """ This class represents a player's session and is a template for individual protocols to communicate with Evennia. Each player gets a session assigned to them whenever they connect to the game server. All communication between game and player goes through their session. """ def __init__(self): "Initiate to avoid AttributeErrors down the line" self.puppet = None self.player = None self.cmdset_storage_string = "" self.cmdset = LazyLoadHandler(self, "cmdset", cmdsethandler.CmdSetHandler, True) def __cmdset_storage_get(self): return [path.strip() for path in self.cmdset_storage_string.split(',')] def __cmdset_storage_set(self, value): self.cmdset_storage_string = ",".join(str(val).strip() for val in make_iter(value)) cmdset_storage = property(__cmdset_storage_get, __cmdset_storage_set) def at_sync(self): """ This is called whenever a session has been resynced with the portal. At this point all relevant attributes have already been set and self.player been assigned (if applicable). Since this is often called after a server restart we need to set up the session as it was. """ global _ObjectDB if not _ObjectDB: from src.objects.models import ObjectDB as _ObjectDB if not self.logged_in: # assign the unloggedin-command set. self.cmdset_storage = settings.CMDSET_UNLOGGEDIN self.cmdset.update(init_mode=True) if self.puid: # reconnect puppet (puid is only set if we are coming # back from a server reload) obj = _ObjectDB.objects.get(id=self.puid) self.player.puppet_object(self.sessid, obj, normal_mode=False) def at_login(self, player): """ Hook called by sessionhandler when the session becomes authenticated. player - the player associated with the session """ self.player = player self.uid = self.player.id self.uname = self.player.username self.logged_in = True self.conn_time = time.time() self.puid = None self.puppet = None self.cmdset_storage = settings.CMDSET_SESSION # Update account's last login time. self.player.last_login = datetime.now() self.player.save() # add the session-level cmdset self.cmdset = LazyLoadHandler(self, "cmdset", cmdsethandler.CmdSetHandler, True) def at_disconnect(self): """ Hook called by sessionhandler when disconnecting this session. """ if self.logged_in: sessid = self.sessid player = self.player _GA(player.dbobj, "unpuppet_object")(sessid) uaccount = player.dbobj uaccount.last_login = datetime.now() uaccount.save() # calling player hook _GA(player.typeclass, "at_disconnect")() self.logged_in = False if not self.sessionhandler.sessions_from_player(player): # no more sessions connected to this player player.is_connected = False def get_player(self): """ Get the player associated with this session """ return self.logged_in and self.player def get_puppet(self): """ Returns the in-game character associated with this session. This returns the typeclass of the object. """ return self.logged_in and self.puppet get_character = get_puppet def get_puppet_or_player(self): """ Returns session if not logged in; puppet if one exists, otherwise return the player. """ if self.logged_in: return self.puppet if self.puppet else self.player return None def log(self, message, channel=True): """ Emits session info to the appropriate outputs and info channels. """ if channel: try: cchan = settings.CHANNEL_CONNECTINFO cchan = ChannelDB.objects.get_channel(cchan[0]) cchan.msg("[%s]: %s" % (cchan.key, message)) except Exception: pass logger.log_infomsg(message) def update_session_counters(self, idle=False): """ Hit this when the user enters a command in order to update idle timers and command counters. """ # Store the timestamp of the user's last command. self.cmd_last = time.time() if not idle: # Increment the user's command counter. self.cmd_total += 1 # Player-visible idle time, not used in idle timeout calcs. self.cmd_last_visible = time.time() def data_in(self, text=None, **kwargs): """ Send User->Evennia. This will in effect execute a command string on the server. Especially handled keywords: oob - this should hold a dictionary of oob command calls from the oob-supporting protocol. """ if text: # this is treated as a command input text = to_unicode(text) # handle the 'idle' command if text.strip() == IDLE_COMMAND: self.update_session_counters(idle=True) return if self.player: # nick replacement puppet = self.player.get_puppet(self.sessid) if puppet: text = puppet.nicks.nickreplace(text, categories=("inputline", "channel"), include_player=True) else: text = self.player.nicks.nickreplace(text, categories=("inputline", "channels"), include_player=False) cmdhandler.cmdhandler(self, text, callertype="session", sessid=self.sessid) self.update_session_counters() if "oob" in kwargs: # handle oob instructions global _OOB_HANDLER if not _OOB_HANDLER: from src.server.oobhandler import OOB_HANDLER as _OOB_HANDLER oobstruct = self.sessionhandler.oobstruct_parser(kwargs.pop("oob", None)) for (funcname, args, kwargs) in oobstruct: if funcname: _OOB_HANDLER.execute_cmd(self, funcname, *args, **kwargs) execute_cmd = data_in # alias def data_out(self, text=None, **kwargs): """ Send Evennia -> User """ self.sessionhandler.data_out(self, text=text, **kwargs) def __eq__(self, other): return self.address == other.address def __str__(self): """ String representation of the user session class. We use this a lot in the server logs. """ symbol = "" if self.logged_in and hasattr(self, "player") and self.player: symbol = "(#%s)" % self.player.id try: if hasattr(self.address, '__iter__'): address = ":".join([str(part) for part in self.address]) else: address = self.address except Exception: address = self.address return "%s%s@%s" % (self.uname, symbol, address) def __unicode__(self): """ Unicode representation """ return u"%s" % str(self) # easy-access functions #def login(self, player): # "alias for at_login" # self.session_login(player) #def disconnect(self): # "alias for session_disconnect" # self.session_disconnect() def msg(self, text='', **kwargs): "alias for at_data_out" self.data_out(text=text, **kwargs) # Dummy API hooks for use during non-loggedin operation def at_cmdset_get(self): "dummy hook all objects with cmdsets need to have" pass # Mock db/ndb properties for allowing easy storage on the session # (note that no databse is involved at all here. session.db.attr = # value just saves a normal property in memory, just like ndb). #@property def ndb_get(self): """ A non-persistent store (ndb: NonDataBase). Everything stored to this is guaranteed to be cleared when a server is shutdown. Syntax is same as for the _get_db_holder() method and property, e.g. obj.ndb.attr = value etc. """ try: return self._ndb_holder except AttributeError: class NdbHolder(object): "Holder for storing non-persistent attributes." def all(self): return [val for val in self.__dict__.keys() if not val.startswith['_']] def __getattribute__(self, key): # return None if no matching attribute was found. try: return object.__getattribute__(self, key) except AttributeError: return None self._ndb_holder = NdbHolder() return self._ndb_holder #@ndb.setter def ndb_set(self, value): "Stop accidentally replacing the db object" string = "Cannot assign directly to ndb object! " string = "Use ndb.attr=value instead." raise Exception(string) #@ndb.deleter def ndb_del(self): "Stop accidental deletion." raise Exception("Cannot delete the ndb object!") ndb = property(ndb_get, ndb_set, ndb_del) db = property(ndb_get, ndb_set, ndb_del) # Mock access method for the session (there is no lock info # at this stage, so we just present a uniform API) def access(self, *args, **kwargs): "Dummy method." return True
def __init__(self, *args, **kwargs): TypedObject.__init__(self, *args, **kwargs) _SA(self, "tags", LazyLoadHandler(self, "tags", TagHandler)) _SA(self, "attributes", LazyLoadHandler(self, "attributes", AttributeHandler)) _SA(self, "aliases", LazyLoadHandler(self, "aliases", AliasHandler))
def __init__(self, *args, **kwargs): super(ScriptDB, self).__init__(*args, **kwargs) _SA(self, "attributes", LazyLoadHandler(self, "attributes", AttributeHandler)) _SA(self, "tags", LazyLoadHandler(self, "tags", TagHandler))
def __init__(self, *args, **kwargs): SharedMemoryModel.__init__(self, *args, **kwargs) self.locks = LazyLoadHandler(self, "locks", LockHandler) self.tags = LazyLoadHandler(self, "tags", TagHandler)
class Command(object): """ Base command Usage: command [args] This is the base command class. Inherit from this to create new commands. The cmdhandler makes the following variables available to the command methods (so you can always assume them to be there): self.caller - the game object calling the command self.cmdstring - the command name used to trigger this command (allows you to know which alias was used, for example) cmd.args - everything supplied to the command following the cmdstring (this is usually what is parsed in self.parse()) cmd.cmdset - the cmdset from which this command was matched (useful only seldomly, notably for help-type commands, to create dynamic help entries and lists) cmd.obj - the object on which this command is defined. If a default command, this is usually the same as caller. The following class properties can/should be defined on your child class: key - identifier for command (e.g. "look") aliases - (optional) list of aliases (e.g. ["l", "loo"]) locks - lock string (default is "cmd:all()") help_category - how to organize this help entry in help system (default is "General") auto_help - defaults to True. Allows for turning off auto-help generation arg_regex - (optional) raw string regex defining how the argument part of the command should look in order to match for this command (e.g. must it be a space between cmdname and arg?) (Note that if auto_help is on, this initial string is also used by the system to create the help entry for the command, so it's a good idea to format it similar to this one) """ # Tie our metaclass, for some convenience cleanup __metaclass__ = CommandMeta # the main way to call this command (e.g. 'look') key = "command" # alternative ways to call the command (e.g. 'l', 'glance', 'examine') aliases = [] # a list of lock definitions on the form # cmd:[NOT] func(args) [ AND|OR][ NOT] func2(args) locks = "" # used by the help system to group commands in lists. help_category = "general" # This allows to turn off auto-help entry creation for individual commands. auto_help = True # auto-set (by Evennia on command instantiation) are: # obj - which object this command is defined on # sessid - which session-id (if any) is responsible for # triggering this command # def __init__(self, **kwargs): """the lockhandler works the same as for objects. optional kwargs will be set as properties on the Command at runtime, overloading evential same-named class properties.""" if kwargs: _init_command(self, **kwargs) self.lockhandler = LazyLoadHandler(self, "lockhandler", LockHandler) def __str__(self): "Print the command" return self.key def __eq__(self, cmd): """ Compare two command instances to each other by matching their key and aliases. input can be either a cmd object or the name of a command. """ try: # first assume input is a command (the most common case) return cmd.key in self._matchset except AttributeError: # probably got a string return cmd in self._matchset def __ne__(self, cmd): """ The logical negation of __eq__. Since this is one of the most called methods in Evennia (along with __eq__) we do some code-duplication here rather than issuing a method-lookup to __eq__. """ try: return not cmd.key in self._matcheset except AttributeError: return not cmd in self._matchset def __contains__(self, query): """ This implements searches like 'if query in cmd'. It's a fuzzy matching used by the help system, returning True if query can be found as a substring of the commands key or its aliases. query (str) - query to match against. Should be lower case. """ return any(query in keyalias for keyalias in self._keyaliases) def match(self, cmdname): """ This is called by the system when searching the available commands, in order to determine if this is the one we wanted. cmdname was previously extracted from the raw string by the system. cmdname (str) is always lowercase when reaching this point. """ return cmdname in self._matchset def access(self, srcobj, access_type="cmd", default=False): """ This hook is called by the cmdhandler to determine if srcobj is allowed to execute this command. It should return a boolean value and is not normally something that need to be changed since it's using the Evennia permission system directly. """ return self.lockhandler.check(srcobj, access_type, default=default) def msg(self, msg="", to_obj=None, from_obj=None, sessid=None, all_sessions=False, **kwargs): """ This is a shortcut instad of calling msg() directly on an object - it will detect if caller is an Object or a Player and also appends self.sessid automatically. msg - text string of message to send to_obj - target object of message. Defaults to self.caller from_obj - source of message. Defaults to to_obj data - optional dictionary of data sessid - supply data only to a unique sessid (normally not used - this is only potentially useful if to_obj is a Player object different from self.caller or self.caller.player) all_sessions (bool) - default is to send only to the session connected to the target object """ from_obj = from_obj or self.caller to_obj = to_obj or from_obj if not sessid: if hasattr(to_obj, "sessid"): # this is the case when to_obj is e.g. a Character sessid = all_sessions and None or to_obj.sessid elif to_obj == self.caller: # this is the case if to_obj is the calling Player sessid = all_sessions and None or self.sessid else: # if to_obj is a different Player, all their sessions # will be notified unless sessid was given specifically sessid = None to_obj.msg(msg, from_obj=from_obj, sessid=sessid, **kwargs) # Common Command hooks def at_pre_cmd(self): """ This hook is called before self.parse() on all commands """ pass def at_post_cmd(self): """ This hook is called after the command has finished executing (after self.func()). """ pass def parse(self): """ Once the cmdhandler has identified this as the command we want, this function is run. If many of your commands have a similar syntax (for example 'cmd arg1 = arg2') you should simply define this once and just let other commands of the same form inherit from this. See the docstring of this module for which object properties are available to use (notably self.args). """ pass def func(self): """ This is the actual executing part of the command. It is called directly after self.parse(). See the docstring of this module for which object properties are available (beyond those set in self.parse()) """ # a simple test command to show the available properties string = "-" * 50 string += "\n{w%s{n - Command variables from evennia:\n" % self.key string += "-" * 50 string += "\nname of cmd (self.key): {w%s{n\n" % self.key string += "cmd aliases (self.aliases): {w%s{n\n" % self.aliases string += "cmd locks (self.locks): {w%s{n\n" % self.locks string += "help category (self.help_category): {w%s{n\n" % self.help_category.capitalize( ) string += "object calling (self.caller): {w%s{n\n" % self.caller string += "object storing cmdset (self.obj): {w%s{n\n" % self.obj string += "command string given (self.cmdstring): {w%s{n\n" % self.cmdstring # show cmdset.key instead of cmdset to shorten output string += fill( "current cmdset (self.cmdset): {w%s{n\n" % (self.cmdset.key if self.cmdset.key else self.cmdset.__class__)) self.caller.msg(string)
class HelpEntry(SharedMemoryModel): """ A generic help entry. An HelpEntry object has the following properties defined: key - main name of entry help_category - which category entry belongs to (defaults to General) entrytext - the actual help text permissions - perm strings Method: access """ # # HelpEntry Database Model setup # # # These database fields are all set using their corresponding properties, # named same as the field, but withtout the db_* prefix. # title of the help entry db_key = models.CharField('help key', max_length=255, unique=True, help_text='key to search for') # help category db_help_category = models.CharField("help category", max_length=255, default="General", help_text='organizes help entries in lists') # the actual help entry text, in any formatting. db_entrytext = models.TextField('help entry', blank=True, help_text='the main body of help text') # lock string storage db_lock_storage = models.TextField('locks', blank=True, help_text='normally view:all().') # tags are primarily used for permissions db_tags = models.ManyToManyField(Tag, null=True, help_text='tags on this object. Tags are simple string markers to identify, group and alias objects.') # (deprecated, only here to allow MUX helpfile load (don't use otherwise)). # TODO: remove this when not needed anymore. db_staff_only = models.BooleanField(default=False) # Database manager objects = HelpEntryManager() _is_deleted = False def __init__(self, *args, **kwargs): SharedMemoryModel.__init__(self, *args, **kwargs) self.locks = LazyLoadHandler(self, "locks", LockHandler) self.tags = LazyLoadHandler(self, "tags", TagHandler) class Meta: "Define Django meta options" verbose_name = "Help Entry" verbose_name_plural = "Help Entries" # Wrapper properties to easily set database fields. These are # @property decorators that allows to access these fields using # normal python operations (without having to remember to save() # etc). So e.g. a property 'attr' has a get/set/del decorator # defined that allows the user to do self.attr = value, # value = self.attr and del self.attr respectively (where self # is the object in question). # key property (wraps db_key) #@property #def __key_get(self): # "Getter. Allows for value = self.key" # return self.db_key ##@key.setter #def __key_set(self, value): # "Setter. Allows for self.key = value" # self.db_key = value # self.save() ##@key.deleter #def __key_del(self): # "Deleter. Allows for del self.key. Deletes entry." # self.delete() #key = property(__key_get, __key_set, __key_del) ## help_category property (wraps db_help_category) ##@property #def __help_category_get(self): # "Getter. Allows for value = self.help_category" # return self.db_help_category ##@help_category.setter #def __help_category_set(self, value): # "Setter. Allows for self.help_category = value" # self.db_help_category = value # self.save() ##@help_category.deleter #def __help_category_del(self): # "Deleter. Allows for del self.help_category" # self.db_help_category = "General" # self.save() #help_category = property(__help_category_get, __help_category_set, __help_category_del) ## entrytext property (wraps db_entrytext) ##@property #def __entrytext_get(self): # "Getter. Allows for value = self.entrytext" # return self.db_entrytext ##@entrytext.setter #def __entrytext_set(self, value): # "Setter. Allows for self.entrytext = value" # self.db_entrytext = value # self.save() ##@entrytext.deleter #def __entrytext_del(self): # "Deleter. Allows for del self.entrytext" # self.db_entrytext = "" # self.save() #entrytext = property(__entrytext_get, __entrytext_set, __entrytext_del) ## permissions property ##@property #def __permissions_get(self): # "Getter. Allows for value = self.permissions. Returns a list of permissions." # return [perm.strip() for perm in self.db_permissions.split(',')] ##@permissions.setter #def __permissions_set(self, value): # "Setter. Allows for self.permissions = value. Stores as a comma-separated string." # if is_iter(value): # value = ",".join([str(val).strip().lower() for val in value]) # self.db_permissions = value # self.save() ##@permissions.deleter #def __permissions_del(self): # "Deleter. Allows for del self.permissions" # self.db_permissions = "" # self.save() #permissions = property(__permissions_get, __permissions_set, __permissions_del) # lock_storage property (wraps db_lock_storage) ##@property #def __lock_storage_get(self): # "Getter. Allows for value = self.lock_storage" # return self.db_lock_storage ##@nick.setter #def __lock_storage_set(self, value): # """Saves the lock_storagetodate. This is usually not called directly, but through self.lock()""" # self.db_lock_storage = value # self.save() ##@nick.deleter #def __lock_storage_del(self): # "Deleter is disabled. Use the lockhandler.delete (self.lock.delete) instead""" # logger.log_errmsg("Lock_Storage (on %s) cannot be deleted. Use obj.lock.delete() instead." % self) #lock_storage = property(__lock_storage_get, __lock_storage_set, __lock_storage_del) # # # HelpEntry main class methods # # def __str__(self): return self.key def __unicode__(self): return u'%s' % self.key def access(self, accessing_obj, access_type='read', default=False): """ Determines if another object has permission to access. accessing_obj - object trying to access this one access_type - type of access sought default - what to return if no lock of access_type was found """ return self.locks.check(accessing_obj, access_type=access_type, default=default)
class HelpEntry(SharedMemoryModel): """ A generic help entry. An HelpEntry object has the following properties defined: key - main name of entry help_category - which category entry belongs to (defaults to General) entrytext - the actual help text permissions - perm strings Method: access """ # # HelpEntry Database Model setup # # # These database fields are all set using their corresponding properties, # named same as the field, but withtout the db_* prefix. # title of the help entry db_key = models.CharField('help key', max_length=255, unique=True, help_text='key to search for') # help category db_help_category = models.CharField( "help category", max_length=255, default="General", help_text='organizes help entries in lists') # the actual help entry text, in any formatting. db_entrytext = models.TextField('help entry', blank=True, help_text='the main body of help text') # lock string storage db_lock_storage = models.TextField('locks', blank=True, help_text='normally view:all().') # tags are primarily used for permissions db_tags = models.ManyToManyField( Tag, null=True, help_text= 'tags on this object. Tags are simple string markers to identify, group and alias objects.' ) # (deprecated, only here to allow MUX helpfile load (don't use otherwise)). # TODO: remove this when not needed anymore. db_staff_only = models.BooleanField(default=False) # Database manager objects = HelpEntryManager() _is_deleted = False def __init__(self, *args, **kwargs): SharedMemoryModel.__init__(self, *args, **kwargs) self.locks = LazyLoadHandler(self, "locks", LockHandler) self.tags = LazyLoadHandler(self, "tags", TagHandler) class Meta: "Define Django meta options" verbose_name = "Help Entry" verbose_name_plural = "Help Entries" # Wrapper properties to easily set database fields. These are # @property decorators that allows to access these fields using # normal python operations (without having to remember to save() # etc). So e.g. a property 'attr' has a get/set/del decorator # defined that allows the user to do self.attr = value, # value = self.attr and del self.attr respectively (where self # is the object in question). # key property (wraps db_key) #@property #def __key_get(self): # "Getter. Allows for value = self.key" # return self.db_key ##@key.setter #def __key_set(self, value): # "Setter. Allows for self.key = value" # self.db_key = value # self.save() ##@key.deleter #def __key_del(self): # "Deleter. Allows for del self.key. Deletes entry." # self.delete() #key = property(__key_get, __key_set, __key_del) ## help_category property (wraps db_help_category) ##@property #def __help_category_get(self): # "Getter. Allows for value = self.help_category" # return self.db_help_category ##@help_category.setter #def __help_category_set(self, value): # "Setter. Allows for self.help_category = value" # self.db_help_category = value # self.save() ##@help_category.deleter #def __help_category_del(self): # "Deleter. Allows for del self.help_category" # self.db_help_category = "General" # self.save() #help_category = property(__help_category_get, __help_category_set, __help_category_del) ## entrytext property (wraps db_entrytext) ##@property #def __entrytext_get(self): # "Getter. Allows for value = self.entrytext" # return self.db_entrytext ##@entrytext.setter #def __entrytext_set(self, value): # "Setter. Allows for self.entrytext = value" # self.db_entrytext = value # self.save() ##@entrytext.deleter #def __entrytext_del(self): # "Deleter. Allows for del self.entrytext" # self.db_entrytext = "" # self.save() #entrytext = property(__entrytext_get, __entrytext_set, __entrytext_del) ## permissions property ##@property #def __permissions_get(self): # "Getter. Allows for value = self.permissions. Returns a list of permissions." # return [perm.strip() for perm in self.db_permissions.split(',')] ##@permissions.setter #def __permissions_set(self, value): # "Setter. Allows for self.permissions = value. Stores as a comma-separated string." # if is_iter(value): # value = ",".join([str(val).strip().lower() for val in value]) # self.db_permissions = value # self.save() ##@permissions.deleter #def __permissions_del(self): # "Deleter. Allows for del self.permissions" # self.db_permissions = "" # self.save() #permissions = property(__permissions_get, __permissions_set, __permissions_del) # lock_storage property (wraps db_lock_storage) ##@property #def __lock_storage_get(self): # "Getter. Allows for value = self.lock_storage" # return self.db_lock_storage ##@nick.setter #def __lock_storage_set(self, value): # """Saves the lock_storagetodate. This is usually not called directly, but through self.lock()""" # self.db_lock_storage = value # self.save() ##@nick.deleter #def __lock_storage_del(self): # "Deleter is disabled. Use the lockhandler.delete (self.lock.delete) instead""" # logger.log_errmsg("Lock_Storage (on %s) cannot be deleted. Use obj.lock.delete() instead." % self) #lock_storage = property(__lock_storage_get, __lock_storage_set, __lock_storage_del) # # # HelpEntry main class methods # # def __str__(self): return self.key def __unicode__(self): return u'%s' % self.key def access(self, accessing_obj, access_type='read', default=False): """ Determines if another object has permission to access. accessing_obj - object trying to access this one access_type - type of access sought default - what to return if no lock of access_type was found """ return self.locks.check(accessing_obj, access_type=access_type, default=default)