From b2ddd34efd0d9b833f9549c028508816551cc5d8 Mon Sep 17 00:00:00 2001 From: Griatch Date: Mon, 22 Jun 2015 21:02:03 +0200 Subject: [PATCH] Updated parts of server/ dir to google docstrings as per #709. --- evennia/server/amp.py | 253 ++++++++++++++++++++++++----- evennia/server/evennia_launcher.py | 109 ++++++++++--- evennia/server/initial_setup.py | 25 ++- evennia/server/manager.py | 38 +++-- evennia/server/models.py | 12 +- evennia/server/oob_cmds.py | 16 ++ evennia/server/oobhandler.py | 14 +- 7 files changed, 382 insertions(+), 85 deletions(-) diff --git a/evennia/server/amp.py b/evennia/server/amp.py index e4264b96f4..9743d408d8 100644 --- a/evennia/server/amp.py +++ b/evennia/server/amp.py @@ -75,15 +75,27 @@ class AmpServerFactory(protocol.ServerFactory): """ def __init__(self, server): """ - server: The Evennia server service instance - protocol: The protocol the factory creates instances of. + Initialize the factory. + + Args: + server (Server): The Evennia server service instance. + protocol (Protocol): The protocol the factory creates + instances of. + """ self.server = server self.protocol = AMPProtocol def buildProtocol(self, addr): """ - Start a new connection, and store it on the service object + Start a new connection, and store it on the service object. + + Args: + addr (str): Connection address. Not used. + + Returns: + protocol (Protocol): The created protocol. + """ #print "Evennia Server connected to Portal at %s." % addr self.server.amp_protocol = AMPProtocol() @@ -95,6 +107,7 @@ class AmpClientFactory(protocol.ReconnectingClientFactory): """ This factory creates an instance of the Portal, an AMPProtocol instances to use to connect + """ # Initial reconnect delay in seconds. initialDelay = 1 @@ -102,12 +115,24 @@ class AmpClientFactory(protocol.ReconnectingClientFactory): maxDelay = 1 def __init__(self, portal): + """ + Initializes the client factory. + + Args: + portal (Portal): Portal instance. + + """ self.portal = portal self.protocol = AMPProtocol def startedConnecting(self, connector): """ Called when starting to try to connect to the MUD server. + + Args: + connector (Connector): Twisted Connector instance representing + this connection. + """ pass #print 'AMP started to connect:', connector @@ -115,6 +140,10 @@ class AmpClientFactory(protocol.ReconnectingClientFactory): def buildProtocol(self, addr): """ Creates an AMPProtocol instance when connecting to the server. + + Args: + addr (str): Connection address. Not used. + """ #print "Portal connected to Evennia server at %s." % addr self.resetDelay() @@ -125,6 +154,12 @@ class AmpClientFactory(protocol.ReconnectingClientFactory): def clientConnectionLost(self, connector, reason): """ Called when the AMP connection to the MUD server is lost. + + Args: + connector (Connector): Twisted Connector instance representing + this connection. + reason (str): Eventual text describing why connection was lost. + """ if hasattr(self, "server_restart_mode"): self.maxDelay = 1 @@ -137,6 +172,12 @@ class AmpClientFactory(protocol.ReconnectingClientFactory): def clientConnectionFailed(self, connector, reason): """ Called when an AMP connection attempt to the MUD server fails. + + Args: + connector (Connector): Twisted Connector instance representing + this connection. + reason (str): Eventual text describing why connection failed. + """ if hasattr(self, "server_restart_mode"): self.maxDelay = 1 @@ -150,7 +191,8 @@ class AmpClientFactory(protocol.ReconnectingClientFactory): class MsgPortal2Server(amp.Command): """ - Message portal -> server + Message Portal -> Server + """ key = "MsgPortal2Server" arguments = [('hashid', amp.String()), @@ -163,7 +205,8 @@ class MsgPortal2Server(amp.Command): class MsgServer2Portal(amp.Command): """ - Message server -> portal + Message Server -> Portal + """ key = "MsgServer2Portal" arguments = [('hashid', amp.String()), @@ -176,11 +219,11 @@ class MsgServer2Portal(amp.Command): class ServerAdmin(amp.Command): """ - Portal -> Server + Administration Portal -> Server + + Sent when the portal needs to perform admin operations on the + server, such as when a new session connects or resyncs - Sent when the portal needs to perform admin - operations on the server, such as when a new - session connects or resyncs """ key = "ServerAdmin" arguments = [('hashid', amp.String()), @@ -193,10 +236,11 @@ class ServerAdmin(amp.Command): class PortalAdmin(amp.Command): """ - Server -> Portal + Administration Server -> Portal + + Sent when the server needs to perform admin operations on the + portal. - Sent when the server needs to perform admin - operations on the portal. """ key = "PortalAdmin" arguments = [('hashid', amp.String()), @@ -209,11 +253,11 @@ class PortalAdmin(amp.Command): class FunctionCall(amp.Command): """ - Bidirectional + Bidirectional Server <-> Portal + + Sent when either process needs to call an arbitrary function in + the other. This does not use the batch-send functionality. - Sent when either process needs to call an - arbitrary function in the other. This does - not use the batch-send functionality. """ key = "FunctionCall" arguments = [('module', amp.String()), @@ -224,7 +268,7 @@ class FunctionCall(amp.Command): response = [('result', amp.String())] -# Helper functions +# Helper functions for pickling. dumps = lambda data: to_str(pickle.dumps(to_str(data), pickle.HIGHEST_PROTOCOL)) loads = lambda data: pickle.loads(to_str(data)) @@ -237,19 +281,22 @@ loads = lambda data: pickle.loads(to_str(data)) class AMPProtocol(amp.AMP): """ This is the protocol that the MUD server and the proxy server - communicate to each other with. AMP is a bi-directional protocol, so - both the proxy and the MUD use the same commands and protocol. + communicate to each other with. AMP is a bi-directional protocol, + so both the proxy and the MUD use the same commands and protocol. + + AMP specifies responder methods here and connect them to + amp.Command subclasses that specify the datatypes of the + input/output of these methods. - AMP specifies responder methods here and connect them to amp.Command - subclasses that specify the datatypes of the input/output of these methods. """ # helper methods def __init__(self, *args, **kwargs): """ - Initialize protocol with some things that need to be - in place already before connecting both on portal and server. + Initialize protocol with some things that need to be in place + already before connecting both on portal and server. + """ self.min_batch_step = 1.0 / BATCH_RATE self.lastsend = time() @@ -259,13 +306,13 @@ class AMPProtocol(amp.AMP): def connectionMade(self): """ - This is called when a connection is established - between server and portal. AMP calls it on both sides, - so we need to make sure to only trigger resync from the - portal side. + This is called when a connection is established between server + and portal. AMP calls it on both sides, so we need to make + sure to only trigger resync from the portal side. """ - self.transport.setTcpNoDelay(True) # this makes for a factor x10 faster sends! + # this makes for a factor x10 faster sends! + self.transport.setTcpNoDelay(True) if hasattr(self.factory, "portal"): # only the portal has the 'portal' property, so we know we are # on the portal side and can initialize the connection. @@ -280,7 +327,15 @@ class AMPProtocol(amp.AMP): # Error handling def errback(self, e, info): - "error handler, to avoid dropping connections on server tracebacks." + """ + Error callback. + Handles errors to avoid dropping connections on server tracebacks. + + Args: + e (Failure): Deferred error instance. + info (str): Error string. + + """ e.trap(Exception) print "AMP Error for %(info)s: %(e)s" % {'info': info, 'e': e.getErrorMessage()} @@ -289,8 +344,17 @@ class AMPProtocol(amp.AMP): """ This will batch data together to send fewer, large batches. + Args: + command (AMP Command): A protocol send command. + sessid (int): A unique Session id. + Kwargs: - force_direct: send direct + force_direct (bool): Send direct, without batching data. + + Returns: + deferreds (list or None): A list of deferreds firing with + as batch parts get sent (or fails). + """ #print "batch_send 1:", command, sessid global _SENDBATCH @@ -343,6 +407,17 @@ class AMPProtocol(amp.AMP): This will receive and unpack data sent as a batch. This both handles too-long data as well as batch-sending very fast- arriving commands. + + Args: + hashid (str): Unique hash id representing this batch in + the cache buffer. + data (str): Data coming over the wire. + ipart (int): Index of this part of the batch (ipart/nparts) + nparts (int): Total number of parts in this batch. + + Returns: + data (str or list): The received data. + """ global _MSGBUFFER if nparts == 1: @@ -364,11 +439,20 @@ class AMPProtocol(amp.AMP): def amp_msg_portal2server(self, hashid, data, ipart, nparts): """ - Relays message to server. This method is executed on the Server. + Relays message to server. This method is executed on the + Server. + + Since AMP has a limit of 65355 bytes per message, it's + possible the data comes in multiple chunks; if so (nparts>1) + we buffer the data and wait for the remaining parts to arrive + before continuing. + + Args: + hashid (str): Unique hash identifying this data batch. + data (str): Data to send (often a part of a batch) + ipart (int): Index of this part of the batch. + nparts (int): Total number of batches. - Since AMP has a limit of 65355 bytes per message, it's possible the - data comes in multiple chunks; if so (nparts>1) we buffer the data - and wait for the remaining parts to arrive before continuing. """ batch = self.batch_recv(hashid, data, ipart, nparts) for (sessid, kwargs) in batch: @@ -382,6 +466,15 @@ class AMPProtocol(amp.AMP): def call_remote_MsgPortal2Server(self, sessid, msg, data=""): """ Access method called by the Portal and executed on the Portal. + + Args: + sessid (int): Unique Session id. + msg (str): Message to send over the wire. + data (str, optional): Optional data. + + Returns: + deferred (Deferred): Asynchronous return. + """ #print "msg portal->server (portal side):", sessid, msg, data return self.batch_send(MsgPortal2Server, sessid, @@ -393,6 +486,18 @@ class AMPProtocol(amp.AMP): def amp_msg_server2portal(self, hashid, data, ipart, nparts): """ Relays message to Portal. This method is executed on the Portal. + + Since AMP has a limit of 65355 bytes per message, it's + possible the data comes in multiple chunks; if so (nparts>1) + we buffer the data and wait for the remaining parts to arrive + before continuing. + + Args: + hashid (str): Unique hash identifying this data batch. + data (str): Data to send (often a part of a batch) + ipart (int): Index of this part of the batch. + nparts (int): Total number of batches. + """ batch = self.batch_recv(hashid, data, ipart, nparts) for (sessid, kwargs) in batch: @@ -406,6 +511,18 @@ class AMPProtocol(amp.AMP): def amp_batch_server2portal(self, hashid, data, ipart, nparts): """ Relays batch data to Portal. This method is executed on the Portal. + + Since AMP has a limit of 65355 bytes per message, it's + possible the data comes in multiple chunks; if so (nparts>1) + we buffer the data and wait for the remaining parts to arrive + before continuing. + + Args: + hashid (str): Unique hash identifying this data batch. + data (str): Data to send (often a part of a batch) + ipart (int): Index of this part of the batch. + nparts (int): Total number of batches. + """ batch = self.batch_recv(hashid, data, ipart, nparts) if batch is not None: @@ -418,7 +535,13 @@ class AMPProtocol(amp.AMP): def call_remote_MsgServer2Portal(self, sessid, msg, data=""): """ - Access method called by the Server and executed on the Server. + Send Message - access method called by the Server and executed on the Server. + + Args: + sessid (int): Unique Session id. + msg (str): Message to send over the wire. + data (str, optional): Extra data. + """ #print "msg server->portal (server side):", sessid, msg, data return self.batch_send(MsgServer2Portal, sessid, msg=msg, data=data) @@ -429,6 +552,17 @@ class AMPProtocol(amp.AMP): This allows the portal to perform admin operations on the server. This is executed on the Server. + Since AMP has a limit of 65355 bytes per message, it's + possible the data comes in multiple chunks; if so (nparts>1) + we buffer the data and wait for the remaining parts to arrive + before continuing. + + Args: + hashid (str): Unique hash identifying this data batch. + data (str): Data to send (often a part of a batch) + ipart (int): Index of this part of the batch. + nparts (int): Total number of batches. + """ #print "serveradmin (server side):", hashid, ipart, nparts batch = self.batch_recv(hashid, data, ipart, nparts) @@ -465,7 +599,15 @@ class AMPProtocol(amp.AMP): def call_remote_ServerAdmin(self, sessid, operation="", data=""): """ - Access method called by the Portal and Executed on the Portal. + Administrative access method called by the Portal and Executed + on the Portal. + + Args: + sessid (int): Session id. + operation (char, optional): Identifier for the server operation, as defined by the + global variables in `evennia/server/amp.py`. + data (str, optional): Data going into the adminstrative operation. + """ #print "serveradmin (portal side):", sessid, ord(operation), data if hasattr(self.factory, "server_restart_mode"): @@ -478,6 +620,18 @@ class AMPProtocol(amp.AMP): """ This allows the server to perform admin operations on the portal. This is executed on the Portal. + + Since AMP has a limit of 65355 bytes per message, it's + possible the data comes in multiple chunks; if so (nparts>1) + we buffer the data and wait for the remaining parts to arrive + before continuing. + + Args: + hashid (str): Unique hash identifying this data batch. + data (str): Data to send (often a part of a batch) + ipart (int): Index of this part of the batch. + nparts (int): Total number of batches. + """ #print "portaladmin (portal side):", sessid, ord(operation), data batch = self.batch_recv(hashid, data, ipart, nparts) @@ -519,7 +673,17 @@ class AMPProtocol(amp.AMP): def call_remote_PortalAdmin(self, sessid, operation="", data=""): """ - Access method called by the server side. + Administrative access method called by the Server side and executed + onthe Portal. + + Args: + sessid (int): Session id. + operation (char, optional): Identifier for the server + operation, as defined by the global variables in + `evennia/server/amp.py`. + data (str, optional): Data going into the adminstrative + operation. + """ if operation == SSYNC: return self.batch_send(PortalAdmin, sessid, force_direct=True, operation=operation, data=data) @@ -529,8 +693,18 @@ class AMPProtocol(amp.AMP): def amp_function_call(self, module, function, args, **kwargs): """ - This allows Portal- and Server-process to call an arbitrary function - in the other process. It is intended for use by plugin modules. + This allows Portal- and Server-process to call an arbitrary + function in the other process. It is intended for use by + plugin modules. + + Args: + module (str or module): The module containing the + `function` to call. + function (str): The name of the function to call in + `module`. + args, kwargs (any): These will be used as args/kwargs to + `function`. + """ args = loads(args) kwargs = loads(kwargs) @@ -561,6 +735,7 @@ class AMPProtocol(amp.AMP): Returns: A deferred that fires with the return value of the remote function call + """ return self.callRemote(FunctionCall, module=modulepath, diff --git a/evennia/server/evennia_launcher.py b/evennia/server/evennia_launcher.py index 21724a1aa2..807f666d01 100644 --- a/evennia/server/evennia_launcher.py +++ b/evennia/server/evennia_launcher.py @@ -315,6 +315,7 @@ ERROR_NODJANGO = \ def evennia_version(): """ Get the Evennia version info from the main package. + """ version = "Unknown" try: @@ -338,6 +339,7 @@ def check_main_evennia_dependencies(): Returns: not_error (bool): True if no dependency error was found. + """ error = False @@ -381,6 +383,7 @@ def set_gamedir(path): """ Set GAMEDIR based on path, by figuring out where the setting file is inside the directory tree. + """ global GAMEDIR @@ -405,6 +408,7 @@ def set_gamedir(path): def create_secret_key(): """ Randomly create the secret key for the settings file + """ import random import string @@ -419,6 +423,7 @@ def create_settings_file(): """ Uses the template settings file to build a working settings file. + """ settings_path = os.path.join(GAMEDIR, "server", "conf", "settings.py") with open(settings_path, 'r') as f: @@ -441,6 +446,10 @@ def create_game_directory(dirname): Initialize a new game directory named dirname at the current path. This means copying the template directory from evennia's root. + + Args: + dirname (str): The directory name to create. + """ global GAMEDIR GAMEDIR = os.path.abspath(os.path.join(CURRENT_DIR, dirname)) @@ -454,14 +463,20 @@ def create_game_directory(dirname): def create_superuser(): - "Create the superuser player" + """ + Create the superuser player + + """ print "\nCreate a superuser below. The superuser is Player #1, the 'owner' account of the server.\n" django.core.management.call_command("createsuperuser", interactive=True) def check_database(): """ - Check database exists + Check so the database exists. + + Returns: + exists (bool): `True` if the database exists, otherwise `False`. """ # Check so a database exists and is accessible from django.db import connection @@ -517,7 +532,11 @@ def check_database(): def getenv(): """ - Get current environment and add PYTHONPATH + Get current environment and add PYTHONPATH. + + Returns: + env (dict): Environment global dict. + """ sep = ";" if os.name == 'nt' else ":" env = os.environ.copy() @@ -527,8 +546,14 @@ def getenv(): def get_pid(pidfile): """ - Get the PID (Process ID) by trying to access - an PID file. + Get the PID (Process ID) by trying to access an PID file. + + Args: + pidfile (str): The path of the pid file. + + Returns: + pid (str): The process id. + """ pid = None if os.path.exists(pidfile): @@ -542,6 +567,10 @@ def del_pid(pidfile): The pidfile should normally be removed after a process has finished, but when sending certain signals they remain, so we need to clean them manually. + + Args: + pidfile (str): The path of the pid file. + """ if os.path.exists(pidfile): os.remove(pidfile) @@ -552,6 +581,15 @@ def kill(pidfile, signal=SIG, succmsg="", errmsg="", restart_file=SERVER_RESTART Send a kill signal to a process based on PID. A customized success/error message will be returned. If clean=True, the system will attempt to manually remove the pid file. + + Args: + pidfile (str): The path of the pidfile to get the PID from. + signal (int, optional): Signal identifier. + succmsg (str, optional): Message to log on success. + errmsg (str, optional): Message to log on failure. + restart_file (str, optional): Restart file location. + restart (bool, optional): Are we in restart mode or not. + """ pid = get_pid(pidfile) if pid: @@ -579,7 +617,14 @@ def kill(pidfile, signal=SIG, succmsg="", errmsg="", restart_file=SERVER_RESTART def show_version_info(about=False): """ - Display version info + Display version info. + + Args: + about (bool): Include ABOUT info as well as version numbers. + + Returns: + version_info (str): A complete version info string. + """ import os, sys import twisted @@ -595,10 +640,15 @@ def show_version_info(about=False): def error_check_python_modules(): """ Import settings modules in settings. This will raise exceptions on - pure python-syntax issues which are hard to catch gracefully - with exceptions in the engine (since they are formatting errors in - the python source files themselves). Best they fail already here + pure python-syntax issues which are hard to catch gracefully with + exceptions in the engine (since they are formatting errors in the + python source files themselves). Best they fail already here before we get any further. + + Raises: + DeprecationWarning: For trying to access various modules + (usually in `settings.py`) which are no longer supported. + """ from django.conf import settings def imp(path, split=True): @@ -661,8 +711,13 @@ def error_check_python_modules(): def init_game_directory(path, check_db=True): """ Try to analyze the given path to find settings.py - this defines - the game directory and also sets PYTHONPATH as well as the - django path. + the game directory and also sets PYTHONPATH as well as the django + path. + + Args: + path (str): Path to new game directory, including its name. + check_db (bool, optional): Check if the databae exists. + """ # set the GAMEDIR path set_gamedir(path) @@ -758,8 +813,14 @@ def run_dummyrunner(number_of_dummies): """ Start an instance of the dummyrunner - The dummy players' behavior can be customized by adding a - dummyrunner_settings.py config file in the game's conf directory. + Args: + number_of_dummies (int): The number of dummy players to start. + + Notes: + The dummy players' behavior can be customized by adding a + ´dummyrunner_settings.py´ config file in the game's conf/ + directory. + """ number_of_dummies = str(int(number_of_dummies)) if number_of_dummies else 1 cmdstr = [sys.executable, EVENNIA_DUMMYRUNNER, "-N", number_of_dummies] @@ -773,8 +834,12 @@ def run_dummyrunner(number_of_dummies): def list_settings(keys): """ - Display the server settings. We only display - the Evennia specific settings here. + Display the server settings. We only display the Evennia specific + settings here. The result will be printed to the terminal. + + Args: + keys (str or list): Setting key or keys to inspect. + """ from importlib import import_module from evennia.utils import evtable @@ -800,6 +865,7 @@ def list_settings(keys): def run_menu(): """ This launches an interactive menu. + """ while True: # menu loop @@ -864,10 +930,12 @@ def server_operation(mode, service, interactive, profiler): """ Handle argument options given on the command line. - mode - str; start/stop etc - service - str; server, portal or all - interactive - bool; use interactive mode or daemon - profiler - run the service under the profiler + Args: + mode (str): Start/stop/restart and so on. + service (str): "server", "portal" or "all". + interactive (bool). Use interactive mode or daemon. + profiler (bool): Run the service under the profiler. + """ cmdstr = [sys.executable, EVENNIA_RUNNER] @@ -936,7 +1004,8 @@ def server_operation(mode, service, interactive, profiler): def main(): """ - Run the evennia main program. + Run the evennia launcher main program. + """ # set up argument parser diff --git a/evennia/server/initial_setup.py b/evennia/server/initial_setup.py index 689a46b826..35b6fb46e8 100644 --- a/evennia/server/initial_setup.py +++ b/evennia/server/initial_setup.py @@ -46,6 +46,7 @@ WARNING_POSTGRESQL_FIX = \ def create_config_values(): """ Creates the initial config values. + """ ServerConfig.objects.conf("site_name", settings.SERVERNAME) ServerConfig.objects.conf("idle_timeout", settings.IDLE_TIMEOUT) @@ -53,6 +54,7 @@ def create_config_values(): def get_god_player(): """ Creates the god user and don't take no for an answer. + """ try: god_player = PlayerDB.objects.get(id=1) @@ -64,6 +66,7 @@ def get_god_player(): def create_objects(): """ Creates the #1 player and Limbo room. + """ print " Creating objects (Player #1 and Limbo room) ..." @@ -122,6 +125,7 @@ def create_objects(): def create_channels(): """ Creates some sensible default channels. + """ print " Creating default channels ..." @@ -137,6 +141,7 @@ def at_initial_setup(): setup. Called very last in the sequence. It tries to import and srun a module settings.AT_INITIAL_SETUP_HOOK_MODULE and will fail silently if this does not exist or fails to load. + """ modname = settings.AT_INITIAL_SETUP_HOOK_MODULE if not modname: @@ -152,10 +157,11 @@ def at_initial_setup(): def reset_server(): """ - We end the initialization by resetting the server. This - makes sure the first login is the same as all the following - ones, particularly it cleans all caches for the special objects. - It also checks so the warm-reset mechanism works as it should. + We end the initialization by resetting the server. This makes sure + the first login is the same as all the following ones, + particularly it cleans all caches for the special objects. It + also checks so the warm-reset mechanism works as it should. + """ from evennia.server.sessionhandler import SESSIONS print " Initial setup complete. Restarting Server once." @@ -164,9 +170,14 @@ def reset_server(): def handle_setup(last_step): """ - Main logic for the module. It allows for restarting - the initialization at any point if one of the modules - should crash. + Main logic for the module. It allows for restarting the + initialization at any point if one of the modules should crash. + + Args: + last_step (int): The last stored successful step, for starting + over on errors. If `< 0`, initialization has finished and no + steps need to be redone. + """ if last_step < 0: diff --git a/evennia/server/manager.py b/evennia/server/manager.py index 527f727775..bf0c7a38e9 100644 --- a/evennia/server/manager.py +++ b/evennia/server/manager.py @@ -6,22 +6,31 @@ from django.db import models class ServerConfigManager(models.Manager): """ - This ServerConfigManager implements methods for searching - and manipulating ServerConfigs directly from the database. + This ServerConfigManager implements methods for searching and + manipulating ServerConfigs directly from the database. - These methods will all return database objects - (or QuerySets) directly. + These methods will all return database objects (or QuerySets) + directly. - ServerConfigs are used to store certain persistent settings for the - server at run-time. - - Evennia-specific: - conf + ServerConfigs are used to store certain persistent settings for + the server at run-time. """ def conf(self, key=None, value=None, delete=False, default=None): """ - Access and manipulate config values + Add, retrieve and manipulate config values. + + Args: + key (str, optional): Name of config. + value (str, optional): Data to store in this config value. + delete (bool, optional): If `True`, delete config with `key`. + default (str, optional): Use when retrieving a config value + by a key that does not exist. + Returns: + all (list): If `key` was not given - all stored config values. + value (str): If `key` was given, this is the stored value, or + `default` if no matching `key` was found. + """ if not key: return self.all() @@ -43,8 +52,13 @@ class ServerConfigManager(models.Manager): def get_mysql_db_version(self): """ - This is a helper method for getting the version string - of a mysql database. + This is a helper method for specifically getting the version + string of a MySQL database. + + Returns: + mysql_version (str): The currently used mysql database + version. + """ from django.db import connection conn = connection.cursor() diff --git a/evennia/server/models.py b/evennia/server/models.py index 1ad6b6cf1e..76cffd0fb6 100644 --- a/evennia/server/models.py +++ b/evennia/server/models.py @@ -30,8 +30,9 @@ class ServerConfig(WeakSharedMemoryModel): On-the fly storage of global settings. Properties defined on ServerConfig: - key - main identifier - value - value stored in key. This is a pickled storage. + + - key: Main identifier + - value: Value stored in key. This is a pickled storage. """ @@ -112,7 +113,12 @@ class ServerConfig(WeakSharedMemoryModel): def store(self, key, value): """ - Wrap the storage (handles pickling) + Wrap the storage. + + Args: + key (str): The name of this store. + value (str): The data to store with this `key`. + """ self.key = key self.value = value diff --git a/evennia/server/oob_cmds.py b/evennia/server/oob_cmds.py index 5311654e82..c69e25388e 100644 --- a/evennia/server/oob_cmds.py +++ b/evennia/server/oob_cmds.py @@ -237,6 +237,7 @@ def oob_report(session, *args, **kwargs): Notes: When the property updates, the monitor will send a MSDP_ARRAY to the session of the form `(SEND, fieldname, new_value)` + Examples: ("REPORT", "CHARACTER_NAME") ("MSDP_TABLE", "CHARACTER_NAME", "Amanda") @@ -268,6 +269,11 @@ def oob_return_field_report(session, fieldname, obj, *args, **kwargs): changes. It is not part of the official MSDP specification but is a callback used by the monitor to format the result before sending it on. + + Args: + session (Session): The Session object controlling this oob function. + fieldname (str): The name of the Field to report on. + """ session.msg(oob=("MSDP_TABLE", (), {fieldname: to_str(getattr(obj, fieldname), force_string=True)})) @@ -283,6 +289,11 @@ def oob_return_attribute_report(session, fieldname, obj, *args, **kwargs): This command is not part of the official MSDP specification but is a callback used by the monitor to format the result before sending it on. + + Args: + session (Session): The Session object controlling this oob function. + fieldname (str): The name of the Attribute to report on. + """ session.msg(oob=("MSDP_TABLE", (), {obj.db_key: to_str(getattr(obj, fieldname), force_string=True)})) @@ -292,6 +303,10 @@ def oob_return_attribute_report(session, fieldname, obj, *args, **kwargs): def oob_unreport(session, *args, **kwargs): """ This removes tracking for the given data. + + Args: + session (Session): Session controling this command. + """ obj = session.get_puppet_or_player() if obj: @@ -330,6 +345,7 @@ def oob_list(session, mode, *args, **kwargs): Examples: oob in: LIST COMMANDS oob out: (COMMANDS, (SEND, REPORT, LIST, ...) + """ mode = mode.upper() if mode == "COMMANDS": diff --git a/evennia/server/oobhandler.py b/evennia/server/oobhandler.py index 075235dbc4..11842d478f 100644 --- a/evennia/server/oobhandler.py +++ b/evennia/server/oobhandler.py @@ -43,6 +43,7 @@ class OOBFieldMonitor(object): the update() method w ill be called by the save mechanism, which in turn will call the user-customizable func() + """ def __init__(self, obj): """ @@ -50,14 +51,19 @@ class OOBFieldMonitor(object): Args: obj (Object): object handler is defined on. + """ self.obj = obj self.subscribers = defaultdict(list) def __call__(self, fieldname): """ - Called by the save() mechanism when the given - field has updated. + Called by the save() mechanism when the given field has + updated. + + Args: + fieldname (str): The field to monitor + """ for sessid, oobtuples in self.subscribers.items(): # oobtuples is a list [(oobfuncname, args, kwargs), ...], @@ -73,12 +79,13 @@ class OOBFieldMonitor(object): Args: sessid (int): Session id oobfuncname (str): oob command to call when field updates - args,kwargs: arguments to pass to oob commjand + args,kwargs (any): arguments to pass to oob commjand Notes: Each sessid may have a list of (oobfuncname, args, kwargs) tuples, all of which will be executed when the field updates. + """ self.subscribers[sessid].append((oobfuncname, args, kwargs)) @@ -88,7 +95,6 @@ class OOBFieldMonitor(object): Args: sessid(int): Session id - Keyword Args: oobfuncname (str, optional): Only delete this cmdname. If not given, delete all.