evennia.commands.cmdhandler¶
Command handler
This module contains the infrastructure for accepting commands on the command line. The processing of a command works as follows:
The calling object (caller) is analyzed based on its callertype.
Cmdsets are gathered from different sources: - object cmdsets: all objects at caller’s location are scanned for non-empty
cmdsets. This includes cmdsets on exits.
caller: the caller is searched for its own currently active cmdset.
account: lastly the cmdsets defined on caller.account are added.
The collected cmdsets are merged together to a combined, current cmdset.
If the input string is empty -> check for CMD_NOINPUT command in current cmdset or fallback to error message. Exit.
The Command Parser is triggered, using the current cmdset to analyze the input string for possible command matches.
If multiple matches are found -> check for CMD_MULTIMATCH in current cmdset, or fallback to error message. Exit.
If no match was found -> check for CMD_NOMATCH in current cmdset or fallback to error message. Exit.
At this point we have found a normal command. We assign useful variables to it that will be available to the command coder at run-time.
We have a unique cmdobject, primed for use. Call all hooks: at_pre_cmd(), cmdobj.parse(), cmdobj.func() and finally at_post_cmd().
Return deferred that will fire with the return from cmdobj.func() (unused by default).
- evennia.commands.cmdhandler.cmdhandler(called_by, raw_string, _testing=False, callertype='session', session=None, cmdobj=None, cmdobj_key=None, **kwargs)[source]¶
This is the main mechanism that handles any string sent to the engine.
- Parameters:
called_by (Session, Account or Object) – Object from which this command was called. which this was called from. What this is depends on the game state.
raw_string (str) – The command string as given on the command line.
_testing (bool, optional) – Used for debug purposes and decides if we should actually execute the command or not. If True, the command instance will be returned.
callertype (str, optional) – One of “session”, “account” or “object”. These are treated in decending order, so when the Session is the caller, it will merge its own cmdset into cmdsets from both Account and eventual puppeted Object (and cmdsets in its room etc). An Account will only include its own cmdset and the Objects and so on. Merge order is the same order, so that Object cmdsets are merged in last, giving them precendence for same-name and same-prio commands.
session (Session, optional) – Relevant if callertype is “account” - the session will help retrieve the correct cmdsets from puppeted objects.
cmdobj (Command, optional) – If given a command instance, this will be executed using called_by as the caller, raw_string representing its arguments and (optionally) cmdobj_key as its input command name. No cmdset lookup will be performed but all other options apply as normal. This allows for running a specific Command within the command system mechanism.
cmdobj_key (string, optional) – Used together with cmdobj keyword to specify which cmdname should be assigned when calling the specified Command instance. This is made available as self.cmdstring when the Command runs. If not given, the command will be assumed to be called as cmdobj.key.
- Keyword Arguments:
kwargs (any) – other keyword arguments will be assigned as named variables on the retrieved command object before it is executed. This is unused in default Evennia but may be used by code to set custom flags or special operating conditions for a command as it executes.
- Returns:
deferred (Deferred) – This deferred is fired with the return value of the command’s func method. This is not used in default Evennia.
- exception evennia.commands.cmdhandler.InterruptCommand[source]¶
Bases:
ExceptionCleanly interrupt a command.
- class evennia.commands.cmdhandler.CmdSet(cmdsetobj=None, key=None)[source]¶
Bases:
objectThis class describes a unique cmdset that understands priorities. CmdSets can be merged and made to perform various set operations on each other. CmdSets have priorities that affect which of their ingoing commands gets used.
In the examples, cmdset A always have higher priority than cmdset B.
key - the name of the cmdset. This can be used on its own for game operations
mergetype (partly from Set theory):
- Union - The two command sets are merged so that as many
commands as possible of each cmdset ends up in the merged cmdset. Same-name commands are merged by priority. This is the most common default. Ex: A1,A3 + B1,B2,B4,B5 = A1,B2,A3,B4,B5
- Intersect - Only commands found in both cmdsets
(i.e. which have same names) end up in the merged cmdset, with the higher-priority cmdset replacing the lower one. Ex: A1,A3 + B1,B2,B4,B5 = A1
- Replace - The commands of this cmdset completely replaces
the lower-priority cmdset’s commands, regardless of if same-name commands exist. Ex: A1,A3 + B1,B2,B4,B5 = A1,A3
- Remove - This removes the relevant commands from the
lower-priority cmdset completely. They are not replaced with anything, so this in effects uses the high-priority cmdset as a filter to affect the low-priority cmdset. Ex: A1,A3 + B1,B2,B4,B5 = B2,B4,B5
- Note: Commands longer than 2 characters and starting
with double underscrores, like ‘__noinput_command’ are considered ‘system commands’ and are excempt from all merge operations - they are ALWAYS included across mergers and only affected if same-named system commands replace them.
- priority- All cmdsets are always merged in pairs of two so that
the higher set’s mergetype is applied to the lower-priority cmdset. Default commands have priority 0, high-priority ones like Exits and Channels have 10 and 9. Priorities can be negative as well to give default commands preference.
- duplicates - determines what happens when two sets of equal
priority merge (only). Defaults to None and has the first of them in the merger (i.e. A above) automatically taking precedence. But if duplicates is true, the result will be a merger with more than one of each name match. This will usually lead to the account receiving a multiple-match error higher up the road, but can be good for things like cmdsets on non-account objects in a room, to allow the system to warn that more than one ‘ball’ in the room has the same ‘kick’ command defined on it, so it may offer a chance to select which ball to kick … Allowing duplicates only makes sense for Union and Intersect, the setting is ignored for the other mergetypes. Note that the duplicates flag is not propagated in a cmdset merger. So A + B = C will result in a cmdset with duplicate commands, but C.duplicates will be None. For duplication to apply to a whole cmdset stack merge, _all_ cmdsets in the stack must have .duplicates=True set.
Finally, if a final cmdset has .duplicates=None (the normal unless created alone with another value), the cmdhandler will assume True for object-based cmdsets and False for all other. This is usually the most intuitive outcome.
- key_mergetype (dict) - allows the cmdset to define a unique
mergetype for particular cmdsets. Format is {CmdSetkeystring:mergetype}. Priorities still apply. Example: {‘Myevilcmdset’,’Replace’} which would make sure for this set to always use ‘Replace’ on Myevilcmdset no matter what overall mergetype this set has.
- no_objs - don’t include any commands from nearby objects
when searching for suitable commands
- no_exits - ignore the names of exits when matching against
commands
- no_channels - ignore the name of channels when matching against
commands (WARNING- this is dangerous since the account can then not even ask staff for help if something goes wrong)
- __init__(cmdsetobj=None, key=None)[source]¶
Creates a new CmdSet instance.
- Parameters:
cmdsetobj (Session, Account, Object, optional) – This is the database object to which this particular instance of cmdset is related. It is often a character but may also be a regular object, Account or Session.
key (str, optional) – The idenfier for this cmdset. This helps if wanting to selectively remov cmdsets.
- add(cmd, allow_duplicates=False)[source]¶
Add a new command or commands to this CmdSet, a list of commands or a cmdset to this cmdset. Note that this is not a merge operation (that is handled by the + operator).
- Parameters:
cmd (Command, list, Cmdset) – This allows for adding one or more commands to this Cmdset in one go. If another Cmdset is given, all its commands will be added.
allow_duplicates (bool, optional) – If set, will not try to remove duplicate cmds in the set. This is needed during the merge process to avoid wiping commands coming from cmdsets with duplicate=True.
Notes
If cmd already exists in set, it will replace the old one (no priority checking etc happens here). This is very useful when overloading default commands).
If cmd is another cmdset class or -instance, the commands of that command set is added to this one, as if they were part of the original cmdset definition. No merging or priority checks are made, rather later added commands will simply replace existing ones to make a unique set.
- at_cmdset_creation()[source]¶
Hook method - this should be overloaded in the inheriting class, and should take care of populating the cmdset by use of self.add().
- duplicates = None¶
- errmessage = ''¶
- get(cmd)[source]¶
Get a command from the cmdset. This is mostly useful to check if the command is part of this cmdset or not.
- Parameters:
cmd (Command or str) – Either the Command object or its key.
- Returns:
cmd (Command) – The first matching Command in the set.
- get_all_cmd_keys_and_aliases(caller=None)[source]¶
Collects keys/aliases from commands
- Parameters:
caller (Object, optional) – If set, this is used to check access permissions on each command. Only commands that pass are returned.
- Returns:
names (list) –
- A list of all command keys and aliases in this cmdset. If caller
was given, this list will only contain commands to which caller passed the call locktype check.
- get_system_cmds()[source]¶
Get system commands in cmdset
- Returns:
sys_cmds (list) – The system commands in the set.
Notes
As far as the Cmdset is concerned, system commands are any commands with a key starting with double underscore __. These are excempt from merge operations.
- key = 'Unnamed CmdSet'¶
- key_mergetypes = {}¶
- make_unique(caller)[source]¶
Remove duplicate command-keys (unsafe)
- Parameters:
caller (object) – Commands on this object will get preference in the duplicate removal.
Notes
This is an unsafe command meant to clean out a cmdset of doublet commands after it has been created. It is useful for commands inheriting cmdsets from the cmdhandler where obj-based cmdsets always are added double. Doublets will be weeded out with preference to commands defined on caller, otherwise just by first-come-first-served.
- mergetype = 'Union'¶
- no_channels = None¶
- no_exits = None¶
- no_objs = None¶
- path = 'evennia.commands.cmdset.CmdSet'¶
- persistent = False¶
- priority = 0¶
- remove(cmd)[source]¶
Remove a command instance from the cmdset.
- Parameters:
cmd (Command or str) – Either the Command object to remove or the key of such a command.
- to_duplicate = ('key', 'cmdsetobj', 'no_exits', 'no_objs', 'no_channels', 'persistent', 'mergetype', 'priority', 'duplicates', 'errmessage')¶
- exception evennia.commands.cmdhandler.ErrorReported(raw_string)[source]¶
Bases:
ExceptionRe-raised when a subsructure already reported the error
- exception evennia.commands.cmdhandler.ExecSystemCommand(syscmd, sysarg)[source]¶
Bases:
ExceptionRun a system command
- exception evennia.commands.cmdhandler.NoCmdSets[source]¶
Bases:
ExceptionNo cmdsets found. Critical error.
- class evennia.commands.cmdhandler.WeakValueDictionary(other=(), /, **kw)[source]¶
Bases:
MutableMappingMapping class that references values weakly.
Entries in the dictionary will be discarded when no strong reference to the value exists anymore
- itervaluerefs()[source]¶
Return an iterator that yields the weak references to the values.
The references are not guaranteed to be ‘live’ at the time they are used, so the result of calling the references needs to be checked before being used. This can be used to avoid creating references that will cause the garbage collector to keep the values around longer than needed.
- pop(k[, d]) v, remove specified key and return the corresponding value.[source]¶
If key is not found, d is returned if given, otherwise KeyError is raised.
- popitem() (k, v), remove and return some (key, value) pair[source]¶
as a 2-tuple; but raise KeyError if D is empty.
- update([E, ]**F) None. Update D from mapping/iterable E and F.[source]¶
If E present and has a .keys() method, does: for k in E.keys(): D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v
- valuerefs()[source]¶
Return a list of weak references to the values.
The references are not guaranteed to be ‘live’ at the time they are used, so the result of calling the references needs to be checked before being used. This can be used to avoid creating references that will cause the garbage collector to keep the values around longer than needed.
- class evennia.commands.cmdhandler.chain(*iterables)¶
Bases:
objectReturn a chain object whose .__next__() method returns elements from the first iterable until it is exhausted, then elements from the next iterable, until all of the iterables are exhausted.
- classmethod from_iterable(iterable, /)¶
Alternative chain() constructor taking a single iterable argument that evaluates lazily.
- evennia.commands.cmdhandler.copy(x)[source]¶
Shallow copy operation on arbitrary Python objects.
See the module’s __doc__ string for more info.
- class evennia.commands.cmdhandler.defaultdict¶
Bases:
dictdefaultdict(default_factory=None, /, […]) –> dict with default factory
The default factory is called without arguments to produce a new value when a key is not present, in __getitem__ only. A defaultdict compares equal to a dict with the same items. All remaining arguments are treated the same as if they were passed to the dict constructor, including keyword arguments.
- __init__(*args, **kwargs)¶
- copy() a shallow copy of D.¶
- default_factory¶
Factory for default value called by __missing__().
- evennia.commands.cmdhandler.deferLater(clock: <InterfaceClass twisted.internet.interfaces.IReactorTime>, delay: float, callable: ~typing.Callable[[...], ~twisted.internet.task._T] | None = None, *args: object, **kw: object) Deferred[_T][source]¶
Call the given function after a certain period of time has passed.
- @param clock: The object which will be used to schedule the delayed
call.
@param delay: The number of seconds to wait before calling the function.
@param callable: The callable to call after the delay, or C{None}.
@param args: The positional arguments to pass to C{callable}.
@param kw: The keyword arguments to pass to C{callable}.
- @return: A deferred that fires with the result of the callable when the
specified time has elapsed.
- evennia.commands.cmdhandler.format_exc(limit=None, chain=True)[source]¶
Like print_exc() but return a string.
- evennia.commands.cmdhandler.get_and_merge_cmdsets(caller, cmdset_providers, callertype, raw_string, report_to=None, cmdid=None)[source]¶
Gather all relevant cmdsets and merge them.
- Parameters:
caller (Session, Account or Object) – The entity executing the command. Which type of object this is depends on the current game state; for example when the user is not logged in, this will be a Session, when being OOC it will be an Account and when puppeting an object this will (often) be a Character Object. In the end it depends on where the cmdset is stored.
cmdset_providers (list) – A list of sorted objects which provide cmdsets.
callertype (str) – This identifies caller as either “account”, “object” or “session” to avoid having to do this check internally.
raw_string (str) – The input string. This is only used for error reporting.
report_to (Object, optional) – If given, this object will receive error messages
- Returns:
cmdset (Deferred) – This deferred fires with the merged cmdset result once merger finishes.
Notes
The cdmsets are merged in order or generality, so that the Object’s cmdset is merged last (and will thus take precedence over same-named and same-prio commands on Account and Session).
- evennia.commands.cmdhandler.inlineCallbacks(f: Callable[[_P], Generator[Deferred[Any], Any, _T]]) Callable[[_P], Deferred[_T]][source]¶
L{inlineCallbacks} helps you write L{Deferred}-using code that looks like a regular sequential function. For example:
@inlineCallbacks def thingummy(): thing = yield makeSomeRequestResultingInDeferred() print(thing) # the result! hoorj!
When you call anything that results in a L{Deferred}, you can simply yield it; your generator will automatically be resumed when the Deferred’s result is available. The generator will be sent the result of the L{Deferred} with the ‘send’ method on generators, or if the result was a failure, ‘throw’.
Things that are not L{Deferred}s may also be yielded, and your generator will be resumed with the same object sent back. This means C{yield} performs an operation roughly equivalent to L{maybeDeferred}.
Your inlineCallbacks-enabled generator will return a L{Deferred} object, which will result in the return value of the generator (or will fail with a failure object if your generator raises an unhandled exception). Inside the generator simply use C{return result} to return a value.
Be aware that generator must not return a L{Deferred}. If you believe the thing you’d like to return could be a L{Deferred}, do this:
result = yield result return result
The L{Deferred} returned from your deferred generator may errback if your generator raised an exception:
@inlineCallbacks def thingummy(): thing = yield makeSomeRequestResultingInDeferred() if thing == 'I love Twisted': # will become the result of the Deferred return 'TWISTED IS GREAT!' else: # will trigger an errback raise Exception('DESTROY ALL LIFE')
You can cancel the L{Deferred} returned from your L{inlineCallbacks} generator before it is fired by your generator completing (either by reaching its end, a C{return} statement, or by calling L{returnValue}). A C{CancelledError} will be raised from the C{yield}ed L{Deferred} that has been cancelled if that C{Deferred} does not otherwise suppress it.
C{inlineCallbacks} behaves very similarly to coroutines. Since Twisted 24.7.0 it is possible to rewrite functions using C{inlineCallbacks} to C{async def} in piecewise manner and be mostly compatible to existing code.
The rewrite process is simply replacing C{inlineCallbacks} decorator with C{async def} and all C{yield} occurrences in the function body with C{await}. The function will no longer return a C{Deferred} but a awaitable coroutine. This return value will obviously not have C{Deferred} methods such as C{addCallback}, but it will be possible to C{yield} it in other code based on C{inlineCallbacks}.
- evennia.commands.cmdhandler.string_suggestions(string, vocabulary, cutoff=0.6, maxnum=3)[source]¶
Given a string and a vocabulary, return a match or a list of suggestions based on string similarity.
- Parameters:
string (str) – A string to search for.
vocabulary (iterable) – A list of available strings.
cutoff (int, 0-1) – Limit the similarity matches (the higher the value, the more exact a match is required).
maxnum (int) – Maximum number of suggestions to return.
- Returns:
suggestions (list) – Suggestions from vocabulary with a similarity-rating that higher than or equal to cutoff. Could be empty if there are no matches.