From 76fa0059ea83d0ed5bc3a5871d62b16873d186a9 Mon Sep 17 00:00:00 2001 From: Griatch Date: Wed, 22 May 2013 18:18:50 +0200 Subject: [PATCH 01/49] First preparations for moving webserver to Server process. --- src/utils/dbserialize.py | 26 ++++++++++++---------- src/utils/idmapper/base.py | 45 ++++++++++++++++++++++++++------------ src/utils/utils.py | 4 ++-- 3 files changed, 48 insertions(+), 27 deletions(-) diff --git a/src/utils/dbserialize.py b/src/utils/dbserialize.py index b1d7682bf1..0c24908480 100644 --- a/src/utils/dbserialize.py +++ b/src/utils/dbserialize.py @@ -31,10 +31,6 @@ from django.contrib.contenttypes.models import ContentType from src.utils.utils import to_str, uses_database from src.utils import logger - - - - __all__ = ("to_pickle", "from_pickle", "do_pickle", "do_unpickle") PICKLE_PROTOCOL = 2 @@ -47,13 +43,21 @@ _FROM_MODEL_MAP = None _TO_MODEL_MAP = None _TO_TYPECLASS = lambda o: hasattr(o, 'typeclass') and o.typeclass or o _IS_PACKED_DBOBJ = lambda o: type(o) == tuple and len(o) == 4 and o[0] == '__packed_dbobj__' -_TO_DATESTRING = lambda o: _GA(o, "db_date_created").strftime("%Y:%m:%d-%H:%M:%S:%f") -if uses_database("mysql"): - from src.server.models import ServerConfig - mysql_version = ServerConfig.objects.get_mysql_db_version() - if mysql_version < '5.6.4': - # mysql <5.6.4 don't support millisecond precision - _TO_DATESTRING = lambda o: _GA(o, "db_date_created").strftime("%Y:%m:%d-%H:%M:%S:000000") +if uses_database("mysql") and ServerConfig.objects.get_mysql_db_version() < '5.6.4': + # mysql <5.6.4 don't support millisecond precision + _DATESTRING = "%Y:%m:%d-%H:%M:%S:000000" +else: + _DATESTRING = "%Y:%m:%d-%H:%M:%S:%f" + +def _TO_DATESTRING(obj): + "this will only be called with valid database objects. Returns datestring on correct form." + try: + return _GA(obj, "db_date_created").strftime(_DATESTRING) + except AttributeError: + # this can happen if object is not yet saved - no datestring is then set + obj.save() + return _GA(obj, "db_date_created").strftime(_DATESTRING) + def _init_globals(): "Lazy importing to avoid circular import issues" diff --git a/src/utils/idmapper/base.py b/src/utils/idmapper/base.py index d56948c57f..c2a7a01280 100755 --- a/src/utils/idmapper/base.py +++ b/src/utils/idmapper/base.py @@ -7,10 +7,12 @@ leave caching unexpectedly (no use if WeakRefs). Also adds cache_size() for monitoring the size of the cache. """ -import os +import os, threading +from twisted.internet import reactor +from twisted.internet.reactor import callFromThread +from twisted.internet.threads import blockingCallFromThread from django.db.models.base import Model, ModelBase -from django.db.models.signals import post_save, pre_delete, \ - post_syncdb +from django.db.models.signals import post_save, pre_delete, post_syncdb from manager import SharedMemoryManager @@ -37,11 +39,19 @@ def _get_pids(): if server_pid and portal_pid: return int(server_pid), int(portal_pid) return None, None -_SELF_PID = os.getpid() -_SERVER_PID = None -_PORTAL_PID = None -_IS_SUBPROCESS = False +# get info about the current process and thread + +_SELF_PID = os.getpid() +_SERVER_PID, _PORTAL_PID = _get_pids() +_IS_SUBPROCESS = (_SERVER_PID and _PORTAL_PID) and not _SELF_PID in (_SERVER_PID, _PORTAL_PID) +_IS_MAIN_THREAD = threading.currentThread().getName() == "MainThread" + +#_SERVER_PID = None +#_PORTAL_PID = None +# #global _SERVER_PID, _PORTAL_PID, _IS_SUBPROCESS, _SELF_PID +# if not _SERVER_PID and not _PORTAL_PID: +# _IS_SUBPROCESS = (_SERVER_PID and _PORTAL_PID) and not _SELF_PID in (_SERVER_PID, _PORTAL_PID) class SharedMemoryModelBase(ModelBase): # CL: upstream had a __new__ method that skipped ModelBase's __new__ if @@ -158,15 +168,22 @@ class SharedMemoryModel(Model): flush_instance_cache = classmethod(flush_instance_cache) def save(cls, *args, **kwargs): - "overload spot for saving" - global _SERVER_PID, _PORTAL_PID, _IS_SUBPROCESS, _SELF_PID - if not _SERVER_PID and not _PORTAL_PID: - _SERVER_PID, _PORTAL_PID = _get_pids() - _IS_SUBPROCESS = (_SERVER_PID and _PORTAL_PID) and (_SERVER_PID != _SELF_PID) and (_PORTAL_PID != _SELF_PID) + "save tracking process/thread issues" + if _IS_SUBPROCESS: - #print "storing in PROC_MODIFIED_OBJS:", cls.db_key, cls.id + # we keep a store of objects modified in subprocesses so + # we know to update their caches in the central process PROC_MODIFIED_OBJS.append(cls) - super(SharedMemoryModel, cls).save(*args, **kwargs) + + if _IS_MAIN_THREAD: + # in main thread - normal operation + super(SharedMemoryModel, cls).save(*args, **kwargs) + else: + # in another thread; make sure to save in reactor thread + def _save_callback(cls, *args, **kwargs): + super(SharedMemoryModel, cls).save(*args, **kwargs) + blockingCallFromThread(reactor, _save_callback, cls, *args, **kwargs) + #callFromThread(_save_callback, cls, *args, **kwargs) # Use a signal so we make sure to catch cascades. def flush_cache(**kwargs): diff --git a/src/utils/utils.py b/src/utils/utils.py index a10d1b473a..503516e5f8 100644 --- a/src/utils/utils.py +++ b/src/utils/utils.py @@ -467,9 +467,9 @@ def delay(delay=2, retval=None, callback=None): """ Delay the return of a value. Inputs: - to_return (any) - this will be returned by this function after a delay delay (int) - the delay in seconds - callback (func(r)) - if given, this will be called with the to_return after delay seconds + retval (any) - this will be returned by this function after a delay + callback (func(retval)) - if given, this will be called with retval after delay seconds Returns: deferred that will fire with to_return after delay seconds """ From 812bdb0f73537a8e057f872595ac472150d0df2c Mon Sep 17 00:00:00 2001 From: Griatch Date: Wed, 22 May 2013 18:40:16 +0200 Subject: [PATCH 02/49] Refactored src/server, splitting out into a portal subdirectory to make it clearer what goes on which "side". --- game/runner.py | 2 +- src/server/portal/__init__.py | 0 src/server/{ => portal}/mccp.py | 2 +- src/server/{ => portal}/msdp.py | 0 src/server/{ => portal}/mssp.py | 0 src/server/{ => portal}/portal.py | 14 +- src/server/portal/portalsessionhandler.py | 167 ++++++++++++++++++++++ src/server/{ => portal}/ssh.py | 0 src/server/{ => portal}/ssl.py | 2 +- src/server/{ => portal}/telnet.py | 4 +- src/server/{ => portal}/ttype.py | 0 src/server/{ => portal}/webclient.py | 0 src/server/sessionhandler.py | 163 --------------------- 13 files changed, 179 insertions(+), 175 deletions(-) create mode 100644 src/server/portal/__init__.py rename src/server/{ => portal}/mccp.py (97%) rename src/server/{ => portal}/msdp.py (100%) rename src/server/{ => portal}/mssp.py (100%) rename src/server/{ => portal}/portal.py (96%) create mode 100644 src/server/portal/portalsessionhandler.py rename src/server/{ => portal}/ssh.py (100%) rename src/server/{ => portal}/ssl.py (98%) rename src/server/{ => portal}/telnet.py (98%) rename src/server/{ => portal}/ttype.py (100%) rename src/server/{ => portal}/webclient.py (100%) diff --git a/game/runner.py b/game/runner.py index f7408c74ce..3bc644065e 100644 --- a/game/runner.py +++ b/game/runner.py @@ -50,7 +50,7 @@ from django.conf import settings # Setup access of the evennia server itself SERVER_PY_FILE = os.path.join(settings.SRC_DIR, 'server/server.py') -PORTAL_PY_FILE = os.path.join(settings.SRC_DIR, 'server/portal.py') +PORTAL_PY_FILE = os.path.join(settings.SRC_DIR, 'server/portal/portal.py') # Get logfile names SERVER_LOGFILE = settings.SERVER_LOG_FILE diff --git a/src/server/portal/__init__.py b/src/server/portal/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/server/mccp.py b/src/server/portal/mccp.py similarity index 97% rename from src/server/mccp.py rename to src/server/portal/mccp.py index 9cf7b34d5d..2e6aa77cd3 100644 --- a/src/server/mccp.py +++ b/src/server/portal/mccp.py @@ -2,7 +2,7 @@ MCCP - Mud Client Compression Protocol -The implements the MCCP v2 telnet protocol as per +This implements the MCCP v2 telnet protocol as per http://tintin.sourceforge.net/mccp/. MCCP allows for the server to compress data when sending to supporting clients, reducing bandwidth by 70-90%.. The compression is done using Python's builtin zlib diff --git a/src/server/msdp.py b/src/server/portal/msdp.py similarity index 100% rename from src/server/msdp.py rename to src/server/portal/msdp.py diff --git a/src/server/mssp.py b/src/server/portal/mssp.py similarity index 100% rename from src/server/mssp.py rename to src/server/portal/mssp.py diff --git a/src/server/portal.py b/src/server/portal/portal.py similarity index 96% rename from src/server/portal.py rename to src/server/portal/portal.py index b871bd434e..ca6bbc4d77 100644 --- a/src/server/portal.py +++ b/src/server/portal/portal.py @@ -11,15 +11,15 @@ import sys import os if os.name == 'nt': # For Windows batchfile we need an extra path insertion here. - sys.path.insert(0, os.path.dirname(os.path.dirname( - os.path.dirname(os.path.abspath(__file__))))) + sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname( + os.path.dirname(os.path.abspath(__file__)))))) from twisted.application import internet, service from twisted.internet import protocol, reactor from twisted.web import server, static from django.conf import settings from src.utils.utils import get_evennia_version, mod_import, make_iter -from src.server.sessionhandler import PORTAL_SESSIONS +from src.server.portal.portalsessionhandler import PORTAL_SESSIONS PORTAL_SERVICES_PLUGIN_MODULES = [mod_import(module) for module in make_iter(settings.PORTAL_SERVICES_PLUGIN_MODULES)] @@ -168,7 +168,7 @@ if TELNET_ENABLED: # Start telnet game connections - from src.server import telnet + from src.server.portal import telnet for interface in TELNET_INTERFACES: if ":" in interface: @@ -192,7 +192,7 @@ if SSL_ENABLED: # Start SSL game connection (requires PyOpenSSL). - from src.server import ssl + from src.server.portal import ssl for interface in SSL_INTERFACES: if ":" in interface: @@ -218,7 +218,7 @@ if SSH_ENABLED: # Start SSH game connections. Will create a keypair in evennia/game if necessary. - from src.server import ssh + from src.server.portal import ssh for interface in SSH_INTERFACES: if ":" in interface: @@ -255,7 +255,7 @@ if WEBSERVER_ENABLED: webclientstr = "" if WEBCLIENT_ENABLED: # create ajax client processes at /webclientdata - from src.server.webclient import WebClient + from src.server.portal.webclient import WebClient webclient = WebClient() webclient.sessionhandler = PORTAL_SESSIONS web_root.putChild("webclientdata", webclient) diff --git a/src/server/portal/portalsessionhandler.py b/src/server/portal/portalsessionhandler.py new file mode 100644 index 0000000000..04228933f8 --- /dev/null +++ b/src/server/portal/portalsessionhandler.py @@ -0,0 +1,167 @@ +""" +Sessionhandler for portal sessions +""" +import time +from src.server.sessionhandler import SessionHandler, PCONN, PDISCONN + +#------------------------------------------------------------ +# Portal-SessionHandler class +#------------------------------------------------------------ +class PortalSessionHandler(SessionHandler): + """ + This object holds the sessions connected to the portal at any time. + It is synced with the server's equivalent SessionHandler over the AMP + connection. + + Sessions register with the handler using the connect() method. This + will assign a new unique sessionid to the session and send that sessid + to the server using the AMP connection. + + """ + + def __init__(self): + """ + Init the handler + """ + self.portal = None + self.sessions = {} + self.latest_sessid = 0 + self.uptime = time.time() + self.connection_time = 0 + + def at_server_connection(self): + """ + Called when the Portal establishes connection with the + Server. At this point, the AMP connection is already + established. + """ + self.connection_time = time.time() + + def connect(self, session): + """ + Called by protocol at first connect. This adds a not-yet authenticated session + using an ever-increasing counter for sessid. + """ + self.latest_sessid += 1 + sessid = self.latest_sessid + session.sessid = sessid + sessdata = session.get_sync_data() + self.sessions[sessid] = session + # sync with server-side + self.portal.amp_protocol.call_remote_ServerAdmin(sessid, + operation=PCONN, + data=sessdata) + def disconnect(self, session): + """ + Called from portal side when the connection is closed from the portal side. + """ + sessid = session.sessid + if sessid in self.sessions: + del self.sessions[sessid] + del session + # tell server to also delete this session + self.portal.amp_protocol.call_remote_ServerAdmin(sessid, + operation=PDISCONN) + + def server_disconnect(self, sessid, reason=""): + """ + Called by server to force a disconnect by sessid + """ + session = self.sessions.get(sessid, None) + if session: + session.disconnect(reason) + if sessid in self.sessions: + # in case sess.disconnect doesn't delete it + del self.sessions[sessid] + del session + + def server_disconnect_all(self, reason=""): + """ + Called by server when forcing a clean disconnect for everyone. + """ + for session in self.sessions.values(): + session.disconnect(reason) + del session + self.sessions = {} + + def server_logged_in(self, sessid, data): + "The server tells us that the session has been authenticated. Updated it." + sess = self.get_session(sessid) + sess.load_sync_data(data) + + def server_session_sync(self, serversessions): + """ + Server wants to save data to the portal, maybe because it's about to shut down. + We don't overwrite any sessions here, just update them in-place and remove + any that are out of sync (which should normally not be the case) + + serversessions - dictionary {sessid:{property:value},...} describing the properties + to sync on all sessions + """ + to_save = [sessid for sessid in serversessions if sessid in self.sessions] + to_delete = [sessid for sessid in self.sessions if sessid not in to_save] + # save protocols + for sessid in to_save: + self.sessions[sessid].load_sync_data(serversessions[sessid]) + # disconnect out-of-sync missing protocols + for sessid in to_delete: + self.server_disconnect(sessid) + + def count_loggedin(self, include_unloggedin=False): + """ + Count loggedin connections, alternatively count all connections. + """ + return len(self.get_sessions(include_unloggedin=include_unloggedin)) + + def session_from_suid(self, suid): + """ + Given a session id, retrieve the session (this is primarily + intended to be called by web clients) + """ + return [sess for sess in self.get_sessions(include_unloggedin=True) + if hasattr(sess, 'suid') and sess.suid == suid] + + def data_in(self, session, string="", data=""): + """ + Called by portal sessions for relaying data coming + in from the protocol to the server. data is + serialized before passed on. + """ + #print "portal_data_in:", string + self.portal.amp_protocol.call_remote_MsgPortal2Server(session.sessid, + msg=string, + data=data) + def announce_all(self, message): + """ + Send message to all connection sessions + """ + for session in self.sessions.values(): + session.data_out(message) + + def data_out(self, sessid, string="", data=""): + """ + Called by server for having the portal relay messages and data + to the correct session protocol. + """ + session = self.sessions.get(sessid, None) + if session: + session.data_out(string, data=data) + + def oob_data_in(self, session, data): + """ + OOB (Out-of-band) data Portal -> Server + """ + print "portal_oob_data_in:", data + self.portal.amp_protocol.call_remote_OOBPortal2Server(session.sessid, + data=data) + + def oob_data_out(self, sessid, data): + """ + OOB (Out-of-band) data Server -> Portal + """ + print "portal_oob_data_out:", data + session = self.sessions.get(sessid, None) + if session: + session.oob_data_out(data) + +PORTAL_SESSIONS = PortalSessionHandler() diff --git a/src/server/ssh.py b/src/server/portal/ssh.py similarity index 100% rename from src/server/ssh.py rename to src/server/portal/ssh.py diff --git a/src/server/ssl.py b/src/server/portal/ssl.py similarity index 98% rename from src/server/ssl.py rename to src/server/portal/ssl.py index b3064731e3..238d3bfd8b 100644 --- a/src/server/ssl.py +++ b/src/server/portal/ssl.py @@ -11,7 +11,7 @@ except ImportError: print " SSL_ENABLED requires PyOpenSSL." sys.exit(5) -from src.server.telnet import TelnetProtocol +from src.server.portal.telnet import TelnetProtocol class SSLProtocol(TelnetProtocol): """ diff --git a/src/server/telnet.py b/src/server/portal/telnet.py similarity index 98% rename from src/server/telnet.py rename to src/server/portal/telnet.py index 27e446e56d..0812d305f7 100644 --- a/src/server/telnet.py +++ b/src/server/portal/telnet.py @@ -10,8 +10,8 @@ sessions etc. import re from twisted.conch.telnet import Telnet, StatefulTelnetProtocol, IAC, LINEMODE from src.server.session import Session -from src.server import ttype, mssp -from src.server.mccp import Mccp, mccp_compress, MCCP +from src.server.portal import ttype, mssp +from src.server.portal.mccp import Mccp, mccp_compress, MCCP from src.utils import utils, ansi, logger _RE_N = re.compile(r"\{n$") diff --git a/src/server/ttype.py b/src/server/portal/ttype.py similarity index 100% rename from src/server/ttype.py rename to src/server/portal/ttype.py diff --git a/src/server/webclient.py b/src/server/portal/webclient.py similarity index 100% rename from src/server/webclient.py rename to src/server/portal/webclient.py diff --git a/src/server/sessionhandler.py b/src/server/sessionhandler.py index 34ca786ec8..6554279d31 100644 --- a/src/server/sessionhandler.py +++ b/src/server/sessionhandler.py @@ -380,167 +380,4 @@ class ServerSessionHandler(SessionHandler): """ self.server.amp_protocol.call_remote_OOBServer2Portal(session.sessid, data=data) - -#------------------------------------------------------------ -# Portal-SessionHandler class -#------------------------------------------------------------ - -class PortalSessionHandler(SessionHandler): - """ - This object holds the sessions connected to the portal at any time. - It is synced with the server's equivalent SessionHandler over the AMP - connection. - - Sessions register with the handler using the connect() method. This - will assign a new unique sessionid to the session and send that sessid - to the server using the AMP connection. - - """ - - def __init__(self): - """ - Init the handler - """ - self.portal = None - self.sessions = {} - self.latest_sessid = 0 - self.uptime = time.time() - self.connection_time = 0 - - def at_server_connection(self): - """ - Called when the Portal establishes connection with the - Server. At this point, the AMP connection is already - established. - """ - self.connection_time = time.time() - - def connect(self, session): - """ - Called by protocol at first connect. This adds a not-yet authenticated session - using an ever-increasing counter for sessid. - """ - self.latest_sessid += 1 - sessid = self.latest_sessid - session.sessid = sessid - sessdata = session.get_sync_data() - self.sessions[sessid] = session - # sync with server-side - self.portal.amp_protocol.call_remote_ServerAdmin(sessid, - operation=PCONN, - data=sessdata) - def disconnect(self, session): - """ - Called from portal side when the connection is closed from the portal side. - """ - sessid = session.sessid - if sessid in self.sessions: - del self.sessions[sessid] - del session - # tell server to also delete this session - self.portal.amp_protocol.call_remote_ServerAdmin(sessid, - operation=PDISCONN) - - def server_disconnect(self, sessid, reason=""): - """ - Called by server to force a disconnect by sessid - """ - session = self.sessions.get(sessid, None) - if session: - session.disconnect(reason) - if sessid in self.sessions: - # in case sess.disconnect doesn't delete it - del self.sessions[sessid] - del session - - def server_disconnect_all(self, reason=""): - """ - Called by server when forcing a clean disconnect for everyone. - """ - for session in self.sessions.values(): - session.disconnect(reason) - del session - self.sessions = {} - - def server_logged_in(self, sessid, data): - "The server tells us that the session has been authenticated. Updated it." - sess = self.get_session(sessid) - sess.load_sync_data(data) - - def server_session_sync(self, serversessions): - """ - Server wants to save data to the portal, maybe because it's about to shut down. - We don't overwrite any sessions here, just update them in-place and remove - any that are out of sync (which should normally not be the case) - - serversessions - dictionary {sessid:{property:value},...} describing the properties - to sync on all sessions - """ - to_save = [sessid for sessid in serversessions if sessid in self.sessions] - to_delete = [sessid for sessid in self.sessions if sessid not in to_save] - # save protocols - for sessid in to_save: - self.sessions[sessid].load_sync_data(serversessions[sessid]) - # disconnect out-of-sync missing protocols - for sessid in to_delete: - self.server_disconnect(sessid) - - def count_loggedin(self, include_unloggedin=False): - """ - Count loggedin connections, alternatively count all connections. - """ - return len(self.get_sessions(include_unloggedin=include_unloggedin)) - - def session_from_suid(self, suid): - """ - Given a session id, retrieve the session (this is primarily - intended to be called by web clients) - """ - return [sess for sess in self.get_sessions(include_unloggedin=True) - if hasattr(sess, 'suid') and sess.suid == suid] - - def data_in(self, session, string="", data=""): - """ - Called by portal sessions for relaying data coming - in from the protocol to the server. data is - serialized before passed on. - """ - #print "portal_data_in:", string - self.portal.amp_protocol.call_remote_MsgPortal2Server(session.sessid, - msg=string, - data=data) - def announce_all(self, message): - """ - Send message to all connection sessions - """ - for session in self.sessions.values(): - session.data_out(message) - - def data_out(self, sessid, string="", data=""): - """ - Called by server for having the portal relay messages and data - to the correct session protocol. - """ - session = self.sessions.get(sessid, None) - if session: - session.data_out(string, data=data) - - def oob_data_in(self, session, data): - """ - OOB (Out-of-band) data Portal -> Server - """ - print "portal_oob_data_in:", data - self.portal.amp_protocol.call_remote_OOBPortal2Server(session.sessid, - data=data) - - def oob_data_out(self, sessid, data): - """ - OOB (Out-of-band) data Server -> Portal - """ - print "portal_oob_data_out:", data - session = self.sessions.get(sessid, None) - if session: - session.oob_data_out(data) - SESSIONS = ServerSessionHandler() -PORTAL_SESSIONS = PortalSessionHandler() From 94f50fcf33de43a8f131689b97a9d4216509de3e Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 23 May 2013 00:02:25 +0200 Subject: [PATCH 03/49] Moved webserver to Server and set up the webclient to work as a stand-alone program on the Portal side. The website link to the webclient is currently pointing to the wrong process, some way to direct that transparently to the Portal-side is needed. --- src/server/portal/portal.py | 47 ++++++++++++++----------------------- src/server/server.py | 38 +++++++++++++++++++++++++++++- src/web/news/urls.py | 4 ++-- src/web/urls.py | 10 ++++---- src/web/webclient/urls.py | 4 ++-- src/web/webclient/views.py | 14 +++++++---- src/web/website/urls.py | 6 ++--- 7 files changed, 77 insertions(+), 46 deletions(-) diff --git a/src/server/portal/portal.py b/src/server/portal/portal.py index ca6bbc4d77..6f71d6832b 100644 --- a/src/server/portal/portal.py +++ b/src/server/portal/portal.py @@ -16,7 +16,7 @@ if os.name == 'nt': from twisted.application import internet, service from twisted.internet import protocol, reactor -from twisted.web import server, static +from twisted.web import server from django.conf import settings from src.utils.utils import get_evennia_version, mod_import, make_iter from src.server.portal.portalsessionhandler import PORTAL_SESSIONS @@ -240,29 +240,9 @@ if SSH_ENABLED: if WEBSERVER_ENABLED: - # Start a django-compatible webserver. + # Start a reverse proxy to relay data to the Server-side webserver - from twisted.python import threadpool - from src.server.webserver import DjangoWebRoot, WSGIWebServer - - # start a thread pool and define the root url (/) as a wsgi resource - # recognized by Django - threads = threadpool.ThreadPool() - web_root = DjangoWebRoot(threads) - # point our media resources to url /media - web_root.putChild("media", static.File(settings.MEDIA_ROOT)) - - webclientstr = "" - if WEBCLIENT_ENABLED: - # create ajax client processes at /webclientdata - from src.server.portal.webclient import WebClient - webclient = WebClient() - webclient.sessionhandler = PORTAL_SESSIONS - web_root.putChild("webclientdata", webclient) - - webclientstr = "/client" - - web_site = server.Site(web_root, logPath=settings.HTTP_LOG_FILE) + from twisted.web import proxy for interface in WEBSERVER_INTERFACES: if ":" in interface: @@ -273,12 +253,22 @@ if WEBSERVER_ENABLED: ifacestr = "-%s" % interface for port in WEBSERVER_PORTS: pstring = "%s:%s" % (ifacestr, port) - # create the webserver - webserver = WSGIWebServer(threads, port, web_site, interface=interface) - webserver.setName('EvenniaWebServer%s' % pstring) - PORTAL.services.addService(webserver) + web_root = proxy.ReverseProxyResource("localhost", port, '') - print " webserver%s%s: %s" % (webclientstr, ifacestr, port) + webclientstr = "" + if WEBCLIENT_ENABLED: + # create ajax client processes at /webclientdata + from src.server.portal.webclient import WebClient + webclient = WebClient() + webclient.sessionhandler = PORTAL_SESSIONS + web_root.putChild("webclientdata", webclient) + webclientstr = "/client" + + web_root = server.Site(web_root, logPath=settings.HTTP_LOG_FILE) + proxy_service = internet.TCPServer(port+1, web_root) + proxy_service.setName('EvenniaWebProxy%s' % pstring) + PORTAL.services.addService(proxy_service) + print " webproxy%s%s: %s" % (webclientstr, ifacestr, port+1) for plugin_module in PORTAL_SERVICES_PLUGIN_MODULES: # external plugin services to start @@ -286,7 +276,6 @@ for plugin_module in PORTAL_SERVICES_PLUGIN_MODULES: print '-' * 50 # end of terminal output - if os.name == 'nt': # Windows only: Set PID file manually f = open(os.path.join(settings.GAME_DIR, 'portal.pid'), 'w') diff --git a/src/server/server.py b/src/server/server.py index f25de51fb6..8836f1a0f0 100644 --- a/src/server/server.py +++ b/src/server/server.py @@ -14,7 +14,7 @@ if os.name == 'nt': # For Windows batchfile we need an extra path insertion here. sys.path.insert(0, os.path.dirname(os.path.dirname( os.path.dirname(os.path.abspath(__file__))))) - +from twisted.web import server, static from twisted.application import internet, service from twisted.internet import reactor, defer import django @@ -57,10 +57,15 @@ AMP_HOST = settings.AMP_HOST AMP_PORT = settings.AMP_PORT AMP_INTERFACE = settings.AMP_INTERFACE +WEBSERVER_PORTS = settings.WEBSERVER_PORTS +WEBSERVER_INTERFACES = settings.WEBSERVER_INTERFACES + # server-channel mappings +WEBSERVER_ENABLED = settings.WEBSERVER_ENABLED and WEBSERVER_PORTS and WEBSERVER_INTERFACES IMC2_ENABLED = settings.IMC2_ENABLED IRC_ENABLED = settings.IRC_ENABLED RSS_ENABLED = settings.RSS_ENABLED +WEBCLIENT_ENABLED = settings.WEBCLIENT_ENABLED #------------------------------------------------------------ @@ -334,6 +339,37 @@ if AMP_ENABLED: amp_service.setName("EvenniaPortal") EVENNIA.services.addService(amp_service) +if WEBSERVER_ENABLED: + + # Start a django-compatible webserver. + + from twisted.python import threadpool + from src.server.webserver import DjangoWebRoot, WSGIWebServer + + # start a thread pool and define the root url (/) as a wsgi resource + # recognized by Django + threads = threadpool.ThreadPool() + web_root = DjangoWebRoot(threads) + # point our media resources to url /media + web_root.putChild("media", static.File(settings.MEDIA_ROOT)) + web_site = server.Site(web_root, logPath=settings.HTTP_LOG_FILE) + + for interface in WEBSERVER_INTERFACES: + if ":" in interface: + print " iPv6 interfaces not yet supported" + continue + ifacestr = "" + if interface != '0.0.0.0' or len(WEBSERVER_INTERFACES) > 1: + ifacestr = "-%s" % interface + for port in WEBSERVER_PORTS: + pstring = "%s:%s" % (ifacestr, port) + # create the webserver + webserver = WSGIWebServer(threads, port, web_site, interface=interface) + webserver.setName('EvenniaWebServer%s' % pstring) + EVENNIA.services.addService(webserver) + + print " webserver%s: %s" % (ifacestr, port) + if IRC_ENABLED: # IRC channel connections diff --git a/src/web/news/urls.py b/src/web/news/urls.py index 10c891d42c..09c4a3b6fe 100755 --- a/src/web/news/urls.py +++ b/src/web/news/urls.py @@ -1,9 +1,9 @@ """ -This structures the url tree for the news application. +This structures the url tree for the news application. It is imported from the root handler, game.web.urls.py. """ -from django.conf.urls.defaults import * +from django.conf.urls import * urlpatterns = patterns('src.web.news.views', (r'^show/(?P\d+)/$', 'show_news'), diff --git a/src/web/urls.py b/src/web/urls.py index bbe83633d6..5ca3bf8a41 100755 --- a/src/web/urls.py +++ b/src/web/urls.py @@ -6,7 +6,7 @@ # http://diveintopython.org/regular_expressions/street_addresses.html#re.matching.2.3 # -from django.conf.urls.defaults import * +from django.conf.urls import * from django.conf import settings from django.contrib import admin from django.views.generic import RedirectView @@ -17,12 +17,12 @@ from django.db.models.loading import cache as model_cache if not model_cache.loaded: model_cache.get_models() -# loop over all settings.INSTALLED_APPS and execute code in +# loop over all settings.INSTALLED_APPS and execute code in # files named admin.py in each such app (this will add those # models to the admin site) admin.autodiscover() -# Setup the root url tree from / +# Setup the root url tree from / urlpatterns = patterns('', # User Authentication @@ -36,11 +36,11 @@ urlpatterns = patterns('', # Page place-holder for things that aren't implemented yet. url(r'^tbi/', 'src.web.website.views.to_be_implemented'), - + # Admin interface url(r'^admin/doc/', include('django.contrib.admindocs.urls')), url(r'^admin/', include(admin.site.urls)), - + # favicon url(r'^favicon\.ico$', RedirectView.as_view(url='/media/images/favicon.ico')), diff --git a/src/web/webclient/urls.py b/src/web/webclient/urls.py index 93702a0673..03f2595d2e 100644 --- a/src/web/webclient/urls.py +++ b/src/web/webclient/urls.py @@ -1,6 +1,6 @@ """ -This structures the (simple) structure of the -webpage 'application'. +This structures the (simple) structure of the +webpage 'application'. """ from django.conf.urls import * diff --git a/src/web/webclient/views.py b/src/web/webclient/views.py index e9ac9910a3..3d097b6935 100644 --- a/src/web/webclient/views.py +++ b/src/web/webclient/views.py @@ -1,19 +1,25 @@ """ -This contains a simple view for rendering the webclient +This contains a simple view for rendering the webclient page and serve it eventual static content. """ -from django.shortcuts import render_to_response +from django.shortcuts import render_to_response, redirect from django.template import RequestContext from django.conf import settings from src.server.sessionhandler import SESSIONS def webclient(request): """ - Webclient page template loading. - """ + Webclient page template loading. + """ + + # analyze request to find which port we are on + if int(request.META["SERVER_PORT"]) == 8000: + # we relay webclient to the portal port + print "Called from port 8000!" + #return redirect("http://localhost:8001/webclient/", permanent=True) # as an example we send the number of connected players to the template pagevars = {'num_players_connected': SESSIONS.player_count()} diff --git a/src/web/website/urls.py b/src/web/website/urls.py index b12603afe1..8bb4bd811e 100644 --- a/src/web/website/urls.py +++ b/src/web/website/urls.py @@ -1,9 +1,9 @@ """ -This structures the (simple) structure of the -webpage 'application'. +This structures the (simple) structure of the +webpage 'application'. """ -from django.conf.urls.defaults import * +from django.conf.urls import * urlpatterns = patterns('src.web.website.views', (r'^$', 'page_index'), From c083fe6266eddee8db14f6b1cc0b6cb98a289c55 Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 23 May 2013 22:58:50 +0200 Subject: [PATCH 04/49] Webserver->Server is working, some more cleanup needed. --- src/server/portal/portal.py | 19 ++++++++++++------- src/server/portal/webclient.py | 10 +++++----- src/server/server.py | 6 +++--- src/settings_default.py | 10 +++++++--- 4 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/server/portal/portal.py b/src/server/portal/portal.py index 6f71d6832b..a39618f6e3 100644 --- a/src/server/portal/portal.py +++ b/src/server/portal/portal.py @@ -55,7 +55,8 @@ WEBCLIENT_ENABLED = settings.WEBCLIENT_ENABLED AMP_HOST = settings.AMP_HOST AMP_PORT = settings.AMP_PORT -AMP_ENABLED = AMP_HOST and AMP_PORT +AMP_INTERFACE = settings.AMP_INTERFACE +AMP_ENABLED = AMP_HOST and AMP_PORT and AMP_INTERFACE #------------------------------------------------------------ @@ -156,6 +157,11 @@ if AMP_ENABLED: from src.server import amp + ifacestr = "" + if AMP_HOST != '127.0.0.1': + ifacestr = "-%s" % AMP_HOST + print ' amp (to Server)%s: %s' % (ifacestr, AMP_PORT) + factory = amp.AmpClientFactory(PORTAL) amp_client = internet.TCPClient(AMP_HOST, AMP_PORT, factory) amp_client.setName('evennia_amp') @@ -251,10 +257,9 @@ if WEBSERVER_ENABLED: ifacestr = "" if interface != '0.0.0.0' or len(WEBSERVER_INTERFACES) > 1: ifacestr = "-%s" % interface - for port in WEBSERVER_PORTS: - pstring = "%s:%s" % (ifacestr, port) - web_root = proxy.ReverseProxyResource("localhost", port, '') - + for proxyport, serverport in WEBSERVER_PORTS: + pstring = "%s:%s<->%s" % (ifacestr, proxyport, serverport) + web_root = proxy.ReverseProxyResource('127.0.0.1', serverport, '') webclientstr = "" if WEBCLIENT_ENABLED: # create ajax client processes at /webclientdata @@ -265,10 +270,10 @@ if WEBSERVER_ENABLED: webclientstr = "/client" web_root = server.Site(web_root, logPath=settings.HTTP_LOG_FILE) - proxy_service = internet.TCPServer(port+1, web_root) + proxy_service = internet.TCPServer(proxyport, web_root, interface=interface) proxy_service.setName('EvenniaWebProxy%s' % pstring) PORTAL.services.addService(proxy_service) - print " webproxy%s%s: %s" % (webclientstr, ifacestr, port+1) + print " webproxy%s%s:%s (<-> %s)" % (webclientstr, ifacestr, proxyport, serverport) for plugin_module in PORTAL_SERVICES_PLUGIN_MODULES: # external plugin services to start diff --git a/src/server/portal/webclient.py b/src/server/portal/webclient.py index afdbd49f2c..746d20d749 100644 --- a/src/server/portal/webclient.py +++ b/src/server/portal/webclient.py @@ -63,11 +63,11 @@ class WebClient(resource.Resource): self.requests = {} self.databuffer = {} - def getChild(self, path, request): - """ - This is the place to put dynamic content. - """ - return self + #def getChild(self, path, request): + # """ + # This is the place to put dynamic content. + # """ + # return self def _responseFailed(self, failure, suid, request): "callback if a request is lost/timed out" diff --git a/src/server/server.py b/src/server/server.py index 8836f1a0f0..1e33daf04a 100644 --- a/src/server/server.py +++ b/src/server/server.py @@ -330,7 +330,7 @@ if AMP_ENABLED: ifacestr = "" if AMP_INTERFACE != '127.0.0.1': ifacestr = "-%s" % AMP_INTERFACE - print ' amp (to Portal)%s:%s' % (ifacestr, AMP_PORT) + print ' amp (to Portal)%s: %s' % (ifacestr, AMP_PORT) from src.server import amp @@ -361,9 +361,9 @@ if WEBSERVER_ENABLED: ifacestr = "" if interface != '0.0.0.0' or len(WEBSERVER_INTERFACES) > 1: ifacestr = "-%s" % interface - for port in WEBSERVER_PORTS: + for proxyport, port in WEBSERVER_PORTS: + # create the webserver (we only need the port for this) pstring = "%s:%s" % (ifacestr, port) - # create the webserver webserver = WSGIWebServer(threads, port, web_site, interface=interface) webserver.setName('EvenniaWebServer%s' % pstring) EVENNIA.services.addService(webserver) diff --git a/src/settings_default.py b/src/settings_default.py index 626d559804..2e4bbed358 100644 --- a/src/settings_default.py +++ b/src/settings_default.py @@ -44,8 +44,12 @@ WEBSERVER_ENABLED = True # attacks. It defaults to allowing all. In production, make # sure to change this to your actual host addresses/IPs. ALLOWED_HOSTS = ["*"] -# A list of ports the Evennia webserver listens on -WEBSERVER_PORTS = [8000] +# The webserver sits behind a Portal proxy. This is a list +# of tuples (proxyport,serverport) used. The proxyports are what +# the Portal proxy presents to the world. The serverports are +# the internal ports the proxy uses to forward data to the Server-side +# webserver (these should not be publicly open) +WEBSERVER_PORTS = [(8000, 5001)] # Interface addresses to listen to. If 0.0.0.0, listen to all. WEBSERVER_INTERFACES = ['0.0.0.0'] # IP addresses that may talk to the server in a reverse proxy configuration, @@ -111,7 +115,7 @@ ENCODINGS = ["utf-8", "latin-1", "ISO-8859-1"] # communicate with it. This is an internal functionality of Evennia, usually # operating between two processes on the same machine. You usually don't need to # change this unless you cannot use the default AMP port/host for whatever reason. -AMP_HOST = 'localhost' +AMP_HOST = '127.0.0.1' AMP_PORT = 5000 AMP_INTERFACE = '127.0.0.1' # Caching speeds up all forms of database access, often considerably. There From 20e093aa26a15df8cfa8f381164a9550f45c9ace Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 23 May 2013 23:42:55 +0200 Subject: [PATCH 05/49] Settings and server configs updated. The caches between server and website threads are still not properly addressed - a change in the admin interface does not immediately translate to a change in-game. --- game/evennia.py | 1 + src/server/portal/portal.py | 5 +---- src/settings_default.py | 2 +- src/utils/idmapper/base.py | 5 +++-- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/game/evennia.py b/game/evennia.py index a42835b352..958786d32f 100755 --- a/game/evennia.py +++ b/game/evennia.py @@ -403,6 +403,7 @@ def error_check_python_modules(): deprstring = "settings.%s should be renamed to %s. If defaults are used, their path/classname must be updated (see src/settings_default.py)." if hasattr(settings, "CMDSET_DEFAULT"): raise DeprecationWarning(deprstring % ("CMDSET_DEFAULT", "CMDSET_CHARACTER")) if hasattr(settings, "CMDSET_OOC"): raise DeprecationWarning(deprstring % ("CMDSET_OOC", "CMDSET_PLAYER")) + if settings.WEBSERVER_ENABLED and not isinstance(settings.WEBSERVER_PORTS[0], tuple): raise DeprecationWarning("settings.WEBSERVER_PORTS must be on the form [(proxyport, serverport), ...]") from src.commands import cmdsethandler if not cmdsethandler.import_cmdset(settings.CMDSET_UNLOGGEDIN, None): print "Warning: CMDSET_UNLOGGED failed to load!" diff --git a/src/server/portal/portal.py b/src/server/portal/portal.py index a39618f6e3..be5b7c1f4b 100644 --- a/src/server/portal/portal.py +++ b/src/server/portal/portal.py @@ -157,10 +157,7 @@ if AMP_ENABLED: from src.server import amp - ifacestr = "" - if AMP_HOST != '127.0.0.1': - ifacestr = "-%s" % AMP_HOST - print ' amp (to Server)%s: %s' % (ifacestr, AMP_PORT) + print ' amp (to Server): %s' % AMP_PORT factory = amp.AmpClientFactory(PORTAL) amp_client = internet.TCPClient(AMP_HOST, AMP_PORT, factory) diff --git a/src/settings_default.py b/src/settings_default.py index 2e4bbed358..13cc9e620e 100644 --- a/src/settings_default.py +++ b/src/settings_default.py @@ -115,7 +115,7 @@ ENCODINGS = ["utf-8", "latin-1", "ISO-8859-1"] # communicate with it. This is an internal functionality of Evennia, usually # operating between two processes on the same machine. You usually don't need to # change this unless you cannot use the default AMP port/host for whatever reason. -AMP_HOST = '127.0.0.1' +AMP_HOST = 'localhost' AMP_PORT = 5000 AMP_INTERFACE = '127.0.0.1' # Caching speeds up all forms of database access, often considerably. There diff --git a/src/utils/idmapper/base.py b/src/utils/idmapper/base.py index c2a7a01280..df110b4ad6 100755 --- a/src/utils/idmapper/base.py +++ b/src/utils/idmapper/base.py @@ -180,10 +180,11 @@ class SharedMemoryModel(Model): super(SharedMemoryModel, cls).save(*args, **kwargs) else: # in another thread; make sure to save in reactor thread + print "saving in another thread!" def _save_callback(cls, *args, **kwargs): super(SharedMemoryModel, cls).save(*args, **kwargs) - blockingCallFromThread(reactor, _save_callback, cls, *args, **kwargs) - #callFromThread(_save_callback, cls, *args, **kwargs) + #blockingCallFromThread(reactor, _save_callback, cls, *args, **kwargs) + callFromThread(_save_callback, cls, *args, **kwargs) # Use a signal so we make sure to catch cascades. def flush_cache(**kwargs): From 70ea21dab89a1d06ef18e2b51c3855ac2a5ed7ab Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 23 May 2013 23:57:21 +0200 Subject: [PATCH 06/49] Added settings for webserver threadpool limits. --- src/server/server.py | 23 ++++++++--------------- src/settings_default.py | 4 ++++ 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/server/server.py b/src/server/server.py index 1e33daf04a..5492bdecbc 100644 --- a/src/server/server.py +++ b/src/server/server.py @@ -348,27 +348,20 @@ if WEBSERVER_ENABLED: # start a thread pool and define the root url (/) as a wsgi resource # recognized by Django - threads = threadpool.ThreadPool() + threads = threadpool.ThreadPool(minthreads=max(1, settings.WEBSERVER_THREADPOOL_LIMITS[0]), + maxthreads=max(1, settings.WEBSERVER_THREADPOOL_LIMITS[1])) web_root = DjangoWebRoot(threads) # point our media resources to url /media web_root.putChild("media", static.File(settings.MEDIA_ROOT)) web_site = server.Site(web_root, logPath=settings.HTTP_LOG_FILE) - for interface in WEBSERVER_INTERFACES: - if ":" in interface: - print " iPv6 interfaces not yet supported" - continue - ifacestr = "" - if interface != '0.0.0.0' or len(WEBSERVER_INTERFACES) > 1: - ifacestr = "-%s" % interface - for proxyport, port in WEBSERVER_PORTS: - # create the webserver (we only need the port for this) - pstring = "%s:%s" % (ifacestr, port) - webserver = WSGIWebServer(threads, port, web_site, interface=interface) - webserver.setName('EvenniaWebServer%s' % pstring) - EVENNIA.services.addService(webserver) + for proxyport, serverport in WEBSERVER_PORTS: + # create the webserver (we only need the port for this) + webserver = WSGIWebServer(threads, serverport, web_site, interface='127.0.0.1') + webserver.setName('EvenniaWebServer%s' % serverport) + EVENNIA.services.addService(webserver) - print " webserver%s: %s" % (ifacestr, port) + print " webserver: %s" % serverport if IRC_ENABLED: diff --git a/src/settings_default.py b/src/settings_default.py index 13cc9e620e..745a8c4a62 100644 --- a/src/settings_default.py +++ b/src/settings_default.py @@ -55,6 +55,10 @@ WEBSERVER_INTERFACES = ['0.0.0.0'] # IP addresses that may talk to the server in a reverse proxy configuration, # like NginX. UPSTREAM_IPS = ['127.0.0.1'] +# The webserver uses threadpool for handling requests. This will scale +# with server load. Set the minimum and maximum number of threads it +# may use as (min, max) (must be > 0) +WEBSERVER_THREADPOOL_LIMITS = (1, 20) # Start the evennia ajax client on /webclient # (the webserver must also be running) WEBCLIENT_ENABLED = True From 0a39b8f65ebb0a3f4207fbdc414dc62f539a8ce1 Mon Sep 17 00:00:00 2001 From: Griatch Date: Fri, 24 May 2013 21:10:31 +0200 Subject: [PATCH 07/49] Webserver move to Server is finished and everything seems to work normally. --- src/objects/admin.py | 3 ++- src/utils/idmapper/base.py | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objects/admin.py b/src/objects/admin.py index 81d3f96501..cf9a66449d 100644 --- a/src/objects/admin.py +++ b/src/objects/admin.py @@ -80,7 +80,7 @@ class ObjectDBAdmin(admin.ModelAdmin): ) #deactivated temporarily, they cause empty objects to be created in admin - inlines = [AliasInline]#, ObjAttributeInline] + #inlines = [AliasInline, ObjAttributeInline] # Custom modification to give two different forms wether adding or not. @@ -111,6 +111,7 @@ class ObjectDBAdmin(admin.ModelAdmin): return super(ObjectDBAdmin, self).get_form(request, obj, **defaults) def save_model(self, request, obj, form, change): + obj.save() if not change: # adding a new object obj = obj.typeclass diff --git a/src/utils/idmapper/base.py b/src/utils/idmapper/base.py index df110b4ad6..5e6032c60a 100755 --- a/src/utils/idmapper/base.py +++ b/src/utils/idmapper/base.py @@ -180,7 +180,6 @@ class SharedMemoryModel(Model): super(SharedMemoryModel, cls).save(*args, **kwargs) else: # in another thread; make sure to save in reactor thread - print "saving in another thread!" def _save_callback(cls, *args, **kwargs): super(SharedMemoryModel, cls).save(*args, **kwargs) #blockingCallFromThread(reactor, _save_callback, cls, *args, **kwargs) From deafb9c544799774aa2c56cee44b1bc321530e8f Mon Sep 17 00:00:00 2001 From: Griatch Date: Sat, 25 May 2013 10:20:26 +0200 Subject: [PATCH 08/49] Added cache-cleaning to the idmapper base class. This works to sync most changes from the admin site-side, but not location changes (which leaves the content cache stale). Thinking of testing the django in-built cache framework instead, maybe using custom fields? --- src/server/caches.py | 29 +++++++++++++++++++++++++---- src/utils/dbserialize.py | 1 + src/utils/idmapper/base.py | 2 ++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/server/caches.py b/src/server/caches.py index d311b19fb4..16f2fbd09f 100644 --- a/src/server/caches.py +++ b/src/server/caches.py @@ -6,6 +6,8 @@ Central caching module. from sys import getsizeof from collections import defaultdict from django.conf import settings +from src.server.models import ServerConfig +from src.utils.utils import to_str, uses_database _ENABLE_LOCAL_CACHES = settings.GAME_CACHE_TYPE @@ -13,6 +15,12 @@ _GA = object.__getattribute__ _SA = object.__setattr__ _DA = object.__delattr__ +if uses_database("mysql") and ServerConfig.objects.get_mysql_db_version() < '5.6.4': + # mysql <5.6.4 don't support millisecond precision + _DATESTRING = "%Y:%m:%d-%H:%M:%S:000000" +else: + _DATESTRING = "%Y:%m:%d-%H:%M:%S:%f" + # OOB hooks (OOB not yet functional, don't use yet) _OOB_FIELD_UPDATE_HOOKS = defaultdict(dict) _OOB_PROP_UPDATE_HOOKS = defaultdict(dict) @@ -35,12 +43,12 @@ def hashid(obj): hid = _GA(obj, "_hashid") except AttributeError: try: - date, idnum = _GA(obj, "db_date_created"), _GA(obj, "id") + date, idnum = _GA(obj, "db_date_created").strftime(_DATESTRING), _GA(obj, "id") except AttributeError: try: # maybe a typeclass, try to go to dbobj obj = _GA(obj, "dbobj") - date, idnum = _GA(obj, "db_date_created"), _GA(obj, "id") + date, idnum = _GA(obj, "db_date_created").strftime(_DATESTRING), _GA(obj, "id") except AttributeError: # this happens if hashing something like ndb. We have to # rely on memory adressing in this case. @@ -194,7 +202,10 @@ if _ENABLE_LOCAL_CACHES: hid = hashid(obj) global _FIELD_CACHE if hid: - del _FIELD_CACHE[hashid(obj)] + try: + del _FIELD_CACHE[hashid(obj)] + except KeyError, e: + pass else: # clean cache completely _FIELD_CACHE = defaultdict(dict) @@ -241,7 +252,10 @@ if _ENABLE_LOCAL_CACHES: hid = hashid(obj) global _PROP_CACHE if hid: - del _PROP_CACHE[hashid(obj)] + try: + del _PROP_CACHE[hid] + except KeyError,e: + pass else: # clean cache completely _PROP_CACHE = defaultdict(dict) @@ -295,6 +309,13 @@ if _ENABLE_LOCAL_CACHES: _ATTR_CACHE = defaultdict(dict) + def flush_obj_caches(obj=None): + "Clean all caches on this object" + flush_field_cache(obj) + flush_prop_cache(obj) + flush_attr_cache(obj) + + else: # local caches disabled. Use simple pass-through replacements diff --git a/src/utils/dbserialize.py b/src/utils/dbserialize.py index 0c24908480..44c1d36a1d 100644 --- a/src/utils/dbserialize.py +++ b/src/utils/dbserialize.py @@ -28,6 +28,7 @@ except ImportError: from django.db import transaction from django.core.exceptions import ObjectDoesNotExist from django.contrib.contenttypes.models import ContentType +from src.server.models import ServerConfig from src.utils.utils import to_str, uses_database from src.utils import logger diff --git a/src/utils/idmapper/base.py b/src/utils/idmapper/base.py index 5e6032c60a..e70f59d8c7 100755 --- a/src/utils/idmapper/base.py +++ b/src/utils/idmapper/base.py @@ -210,6 +210,8 @@ def update_cached_instance(sender, instance, **kwargs): if not hasattr(instance, 'cache_instance'): return sender.cache_instance(instance) + from src.server.caches import flush_obj_caches + flush_obj_caches(instance) post_save.connect(update_cached_instance) def cache_size(mb=True): From 8202dba5965d97609f665f2d26d2498f9e50ac80 Mon Sep 17 00:00:00 2001 From: Griatch Date: Wed, 29 May 2013 16:16:28 +0200 Subject: [PATCH 09/49] Changed cache system to use Django's cache mechanism. Changed field caches to make use of Django signalling instead of custom caching calls (this should make the system consistent also when called from the webserver). Created a wrapper system for easily wrapping fields with a default wrapper (so as to not have to explicitly define the properties (such as objdb.key) which all just do the same thing - load from the field and make sure to call save(). --- src/server/caches.py | 706 +++++++++++++++++++++---------------- src/server/server.py | 6 + src/settings_default.py | 25 +- src/typeclasses/models.py | 32 +- src/utils/idmapper/base.py | 55 ++- 5 files changed, 490 insertions(+), 334 deletions(-) diff --git a/src/server/caches.py b/src/server/caches.py index 16f2fbd09f..d5ad57d6b5 100644 --- a/src/server/caches.py +++ b/src/server/caches.py @@ -2,14 +2,8 @@ Central caching module. """ - -from sys import getsizeof -from collections import defaultdict -from django.conf import settings from src.server.models import ServerConfig -from src.utils.utils import to_str, uses_database - -_ENABLE_LOCAL_CACHES = settings.GAME_CACHE_TYPE +from src.utils.utils import uses_database, to_str _GA = object.__getattribute__ _SA = object.__setattr__ @@ -21,16 +15,8 @@ if uses_database("mysql") and ServerConfig.objects.get_mysql_db_version() < '5.6 else: _DATESTRING = "%Y:%m:%d-%H:%M:%S:%f" -# OOB hooks (OOB not yet functional, don't use yet) -_OOB_FIELD_UPDATE_HOOKS = defaultdict(dict) -_OOB_PROP_UPDATE_HOOKS = defaultdict(dict) -_OOB_ATTR_UPDATE_HOOKS = defaultdict(dict) -_OOB_NDB_UPDATE_HOOKS = defaultdict(dict) -_OOB_CUSTOM_UPDATE_HOOKS = defaultdict(dict) -_OOB_HANDLER = None # set by oob handler when it initializes - -def hashid(obj): +def hashid(obj, suffix=""): """ Returns a per-class unique that combines the object's class name with its idnum and creation time. This makes this id unique also @@ -57,301 +43,425 @@ def hashid(obj): # this will happen if setting properties on an object which is not yet saved return None # build the hashid - hid = "%s-%s-#%s" % (_GA(obj, "__class__"), date, idnum) + hid = "%s-%s-#%s%s" % (_GA(obj, "__class__"), date, idnum, suffix) + hid = hid.replace(" ", "") _SA(obj, "_hashid", hid) - return hid + return to_str(hid) -# oob helper functions -def register_oob_update_hook(obj,name, entity="field"): + +# signal handlers + +from django.core.cache import get_cache +#from django.db.models.signals import pre_save, pre_delete, post_init + +# field cache + +_FIELD_CACHE = get_cache("field_cache") +if not _FIELD_CACHE: + raise RuntimeError("settings.CACHE does not contain a 'field_cache' entry!") + +# callback before saving an object + +def field_pre_save(sender, **kwargs): """ - Register hook function to be called when field/property/db/ndb is updated. - Given function will be called with function(obj, entityname, newvalue, *args, **kwargs) - entity - one of "field", "property", "db", "ndb" or "custom" + Called at the beginning of the save operation. The save method + must be called with the update_fields keyword in order to """ - hid = hashid(obj) - if hid: - if entity == "field": - global _OOB_FIELD_UPDATE_HOOKS - _OOB_FIELD_UPDATE_HOOKS[hid][name] = True - return - elif entity == "property": - global _OOB_PROP_UPDATE_HOOKS - _OOB_PROP_UPDATE_HOOKS[hid][name] = True - elif entity == "db": - global _OOB_ATTR_UPDATE_HOOKS - _OOB_ATTR_UPDATE_HOOKS[hid][name] = True - elif entity == "ndb": - global _OOB_NDB_UPDATE_HOOKS - _OOB_NDB_UPDATE_HOOKS[hid][name] = True - elif entity == "custom": - global _OOB_CUSTOM_UPDATE_HOOKS - _OOB_CUSTOM_UPDATE_HOOKS[hid][name] = True - else: - return None + global _FIELD_CACHE -def unregister_oob_update_hook(obj, name, entity="property"): - """ - Un-register a report hook - """ - hid = hashid(obj) - if hid: - global _OOB_FIELD_UPDATE_HOOKS,_OOB_PROP_UPDATE_HOOKS, _OOB_ATTR_UPDATE_HOOKS - global _OOB_CUSTOM_UPDATE_HOOKS, _OOB_NDB_UPDATE_HOOKS - if entity == "field" and name in _OOB_FIELD_UPDATE_HOOKS: - del _OOB_FIELD_UPDATE_HOOKS[hid][name] - elif entity == "property" and name in _OOB_PROP_UPDATE_HOOKS: - del _OOB_PROP_UPDATE_HOOKS[hid][name] - elif entity == "db" and name in _OOB_ATTR_UPDATE_HOOKS: - del _OOB_ATTR_UPDATE_HOOKS[hid][name] - elif entity == "ndb" and name in _OOB_NDB_UPDATE_HOOKS: - del _OOB_NDB_UPDATE_HOOKS[hid][name] - elif entity == "custom" and name in _OOB_CUSTOM_UPDATE_HOOKS: - del _OOB_CUSTOM_UPDATE_HOOKS[hid][name] - else: - return None - -def call_ndb_hooks(obj, attrname, value): - """ - No caching is done of ndb here, but - we use this as a way to call OOB hooks. - """ - hid = hashid(obj) - if hid: - oob_hook = _OOB_NDB_UPDATE_HOOKS[hid].get(attrname) - if oob_hook: - oob_hook[0](obj.typeclass, attrname, value, *oob_hook[1], **oob_hook[2]) - -def call_custom_hooks(obj, attrname, value): - """ - Custom handler for developers adding their own oob hooks, e.g. to - custom typeclass properties. - """ - hid = hashid(obj) - if hid: - oob_hook = _OOB_CUSTOM_UPDATE_HOOKS[hid].get(attrname) - if oob_hook: - oob_hook[0](obj.typeclass, attrname, value, *oob_hook[1], **oob_hook[2]) - - -if _ENABLE_LOCAL_CACHES: - - # Cache stores - _ATTR_CACHE = defaultdict(dict) - _FIELD_CACHE = defaultdict(dict) - _PROP_CACHE = defaultdict(dict) - - - def get_cache_sizes(): - """ - Get cache sizes, expressed in number of objects and memory size in MB - """ - global _ATTR_CACHE, _FIELD_CACHE, _PROP_CACHE - - attr_n = sum(len(dic) for dic in _ATTR_CACHE.values()) - attr_mb = sum(sum(getsizeof(obj) for obj in dic.values()) for dic in _ATTR_CACHE.values()) / 1024.0 - - field_n = sum(len(dic) for dic in _FIELD_CACHE.values()) - field_mb = sum(sum([getsizeof(obj) for obj in dic.values()]) for dic in _FIELD_CACHE.values()) / 1024.0 - - prop_n = sum(len(dic) for dic in _PROP_CACHE.values()) - prop_mb = sum(sum([getsizeof(obj) for obj in dic.values()]) for dic in _PROP_CACHE.values()) / 1024.0 - - return (attr_n, attr_mb), (field_n, field_mb), (prop_n, prop_mb) - - # on-object database field cache - def get_field_cache(obj, name): - "On-model Cache handler." - global _FIELD_CACHE - hid = hashid(obj) - if hid: - try: - return _FIELD_CACHE[hid][name] - except KeyError: - val = _GA(obj, "db_%s" % name) - _FIELD_CACHE[hid][name] = val - return val - return _GA(obj, "db_%s" % name) - - def set_field_cache(obj, name, val): - "On-model Cache setter. Also updates database." - _SA(obj, "db_%s" % name, val) - _GA(obj, "save")() - hid = hashid(obj) - if hid: - global _FIELD_CACHE - _FIELD_CACHE[hid][name] = val - # oob hook functionality - if _OOB_FIELD_UPDATE_HOOKS[hid].get(name): - _OOB_HANDLER.update(hid, name, val) - - def del_field_cache(obj, name): - "On-model cache deleter" - hid = hashid(obj) - _SA(obj, "db_%s" % name, None) - _GA(obj, "save")() - if hid: - try: - del _FIELD_CACHE[hid][name] - except KeyError: - pass - if _OOB_FIELD_UPDATE_HOOKS[hid].get(name): - _OOB_HANDLER.update(hid, name, None) - - def flush_field_cache(obj=None): - "On-model cache resetter" - hid = hashid(obj) - global _FIELD_CACHE - if hid: - try: - del _FIELD_CACHE[hashid(obj)] - except KeyError, e: - pass - else: - # clean cache completely - _FIELD_CACHE = defaultdict(dict) - - # on-object property cache (unrelated to database) - # Note that the get/set_prop_cache handler do not actually - # get/set the property "on" the object but only reads the - # value to/from the cache. This is intended to be used - # with a get/setter property on the object. - - def get_prop_cache(obj, name, default=None): - "On-model Cache handler." - global _PROP_CACHE - hid = hashid(obj) - if hid: - try: - val = _PROP_CACHE[hid][name] - except KeyError: - return default - _PROP_CACHE[hid][name] = val - return val - return default - - def set_prop_cache(obj, name, val): - "On-model Cache setter. Also updates database." - hid = hashid(obj) - if hid: - global _PROP_CACHE - _PROP_CACHE[hid][name] = val - # oob hook functionality - oob_hook = _OOB_PROP_UPDATE_HOOKS[hid].get(name) - if oob_hook: - oob_hook[0](obj.typeclass, name, val, *oob_hook[1], **oob_hook[2]) - - - def del_prop_cache(obj, name): - "On-model cache deleter" + if kwargs.pop("raw", False): return + instance = kwargs.pop("instance") + fields = kwargs.pop("update_fields", None) + if fields: + # this is a list of strings at this point. We want field objects + fields = (instance._meta.get_field_by_name(field)[0] for field in fields) + else: + # meta.fields are already field objects + fields = instance._meta.fields + for field in fields: + fieldname = field.name + new_value = field.value_from_object(instance) + handlername = "_%s_handler" % fieldname try: - del _PROP_CACHE[hashid(obj)][name] - except KeyError: - pass - def flush_prop_cache(obj=None): - "On-model cache resetter" - hid = hashid(obj) - global _PROP_CACHE + handler = _GA(instance, handlername) + except AttributeError: + handler = None + hid = hashid(instance, "-%s" % fieldname) + if callable(handler): + old_value = _FIELD_CACHE.get(hid) if hid else None + # the handler may modify the stored value in various ways + # don't catch exceptions, the handler must work! + new_value = handler(instance, new_value, oldval=old_value) + # we re-assign this to the field, save() will pick it up from there + _SA(instance, fieldname, new_value) if hid: - try: - del _PROP_CACHE[hid] - except KeyError,e: - pass - else: - # clean cache completely - _PROP_CACHE = defaultdict(dict) + # update cache + _FIELD_CACHE.set(hid, new_value) - # attribute cache +# goes into server: +#pre_save.connect(field_pre_save, dispatch_uid="fieldcache") - def get_attr_cache(obj, attrname): - """ - Attribute cache store - """ - return _ATTR_CACHE[hashid(obj)].get(attrname, None) - - def set_attr_cache(obj, attrname, attrobj): - """ - Cache an attribute object - """ - hid = hashid(obj) - if hid: - global _ATTR_CACHE - _ATTR_CACHE[hid][attrname] = attrobj - # oob hook functionality - oob_hook = _OOB_ATTR_UPDATE_HOOKS[hid].get(attrname) - if oob_hook: - oob_hook[0](obj.typeclass, attrname, attrobj.value, *oob_hook[1], **oob_hook[2]) - - def del_attr_cache(obj, attrname): - """ - Remove attribute from cache - """ - global _ATTR_CACHE - try: - _ATTR_CACHE[hashid(obj)][attrname].no_cache = True - del _ATTR_CACHE[hashid(obj)][attrname] - except KeyError: - pass - - def flush_attr_cache(obj=None): - """ - Flush the attribute cache for this object. - """ - global _ATTR_CACHE - if obj: - for attrobj in _ATTR_CACHE[hashid(obj)].values(): - attrobj.no_cache = True - del _ATTR_CACHE[hashid(obj)] - else: - # clean cache completely - for objcache in _ATTR_CACHE.values(): - for attrobj in objcache.values(): - attrobj.no_cache = True - _ATTR_CACHE = defaultdict(dict) +## attr cache - caching the attribute objects related to a given object to +## avoid lookups more than necessary (this makes attributes en par in speed +## to any property). The signal is triggered by the Attribute itself when it +## is created or deleted (it holds a reference to the object) +# +#_ATTR_CACHE = get_cache("attr_cache") +#if not _ATTR_CACHE: +# raise RuntimeError("settings.CACHE does not contain an 'attr_cache' entry!") +# +#def attr_post_init(sender, **kwargs): +# "Called when attribute is created or retrieved in connection with obj." +# hid = hashid(sender.db_obj, "-%s" % sender.db_key) +# _ATTR_CACHE.set(hid, sender) +#def attr_pre_delete(sender, **kwargs): +# "Called when attribute is deleted (del_attribute)" +# hid = hashid(sender.db_obj, "-%s" % sender.db_key) +# _ATTR_CACHE.delete(hid) +# +### goes into server: +#from src.objects.models import ObjAttribute +#from src.scripts.models import ScriptAttribute +#from src.players.models import PlayerAttribute +#post_init.connect(attr_post_init, sender=ObjAttribute, dispatch_uid="objattrcache") +#post_init.connect(attr_post_init, sender=ScriptAttribute, dispatch_uid="scriptattrcache") +#post_init.connect(attr_post_init, sender=PlayerAttribute, dispatch_uid="playerattrcache") +#pre_delete.connect(attr_pre_delete, sender=ObjAttribute, dispatch_uid="objattrcache") +#pre_delete.connect(attr_pre_delete, sender=ScriptAttribute, dispatch_uid="scriptattrcache") +#pre_delete.connect(attr_pre_delete, sender=PlayerAttribute, dispatch_uid="playerattrcache") +# +# +## property cache - this doubles as a central cache and as a way +## to trigger oob on such changes. +# +#from django.dispatch import Signal +#_PROP_CACHE = get_cache("prop_cache") +#if not _PROP_CACHE: +# raise RuntimeError("settings.CACHE does not contain a 'prop_cache' entry!") +# +#PROP_POST_UPDATE = Signal(providing_args=["propname", "propvalue"]) +# +#def prop_update(sender, **kwargs): +# "Called when a propery is updated. kwargs are propname and propvalue." +# propname, propvalue = kwargs.pop("propname", None), kwargs.pop("propvalue", None) +# if propname == None: return +# hid = hashid(sender, "-%s" % propname) +# _PROP_CACHE.set(hid, propvalue) +# +#PROP_POST_UPDATE.connect(prop_update, dispatch_uid="propcache") +# +# - def flush_obj_caches(obj=None): - "Clean all caches on this object" - flush_field_cache(obj) - flush_prop_cache(obj) - flush_attr_cache(obj) -else: + + + + + +#_ENABLE_LOCAL_CACHES = settings.GAME_CACHE_TYPE +## oob helper functions +# OOB hooks (OOB not yet functional, don't use yet) +#_OOB_FIELD_UPDATE_HOOKS = defaultdict(dict) +#_OOB_PROP_UPDATE_HOOKS = defaultdict(dict) +#_OOB_ATTR_UPDATE_HOOKS = defaultdict(dict) +#_OOB_NDB_UPDATE_HOOKS = defaultdict(dict) +#_OOB_CUSTOM_UPDATE_HOOKS = defaultdict(dict) +# +#_OOB_HANDLER = None # set by oob handler when it initializes +#def register_oob_update_hook(obj,name, entity="field"): +# """ +# Register hook function to be called when field/property/db/ndb is updated. +# Given function will be called with function(obj, entityname, newvalue, *args, **kwargs) +# entity - one of "field", "property", "db", "ndb" or "custom" +# """ +# hid = hashid(obj) +# if hid: +# if entity == "field": +# global _OOB_FIELD_UPDATE_HOOKS +# _OOB_FIELD_UPDATE_HOOKS[hid][name] = True +# return +# elif entity == "property": +# global _OOB_PROP_UPDATE_HOOKS +# _OOB_PROP_UPDATE_HOOKS[hid][name] = True +# elif entity == "db": +# global _OOB_ATTR_UPDATE_HOOKS +# _OOB_ATTR_UPDATE_HOOKS[hid][name] = True +# elif entity == "ndb": +# global _OOB_NDB_UPDATE_HOOKS +# _OOB_NDB_UPDATE_HOOKS[hid][name] = True +# elif entity == "custom": +# global _OOB_CUSTOM_UPDATE_HOOKS +# _OOB_CUSTOM_UPDATE_HOOKS[hid][name] = True +# else: +# return None +# +#def unregister_oob_update_hook(obj, name, entity="property"): +# """ +# Un-register a report hook +# """ +# hid = hashid(obj) +# if hid: +# global _OOB_FIELD_UPDATE_HOOKS,_OOB_PROP_UPDATE_HOOKS, _OOB_ATTR_UPDATE_HOOKS +# global _OOB_CUSTOM_UPDATE_HOOKS, _OOB_NDB_UPDATE_HOOKS +# if entity == "field" and name in _OOB_FIELD_UPDATE_HOOKS: +# del _OOB_FIELD_UPDATE_HOOKS[hid][name] +# elif entity == "property" and name in _OOB_PROP_UPDATE_HOOKS: +# del _OOB_PROP_UPDATE_HOOKS[hid][name] +# elif entity == "db" and name in _OOB_ATTR_UPDATE_HOOKS: +# del _OOB_ATTR_UPDATE_HOOKS[hid][name] +# elif entity == "ndb" and name in _OOB_NDB_UPDATE_HOOKS: +# del _OOB_NDB_UPDATE_HOOKS[hid][name] +# elif entity == "custom" and name in _OOB_CUSTOM_UPDATE_HOOKS: +# del _OOB_CUSTOM_UPDATE_HOOKS[hid][name] +# else: +# return None +# +#def call_ndb_hooks(obj, attrname, value): +# """ +# No caching is done of ndb here, but +# we use this as a way to call OOB hooks. +# """ +# hid = hashid(obj) +# if hid: +# oob_hook = _OOB_NDB_UPDATE_HOOKS[hid].get(attrname) +# if oob_hook: +# oob_hook[0](obj.typeclass, attrname, value, *oob_hook[1], **oob_hook[2]) +# +#def call_custom_hooks(obj, attrname, value): +# """ +# Custom handler for developers adding their own oob hooks, e.g. to +# custom typeclass properties. +# """ +# hid = hashid(obj) +# if hid: +# oob_hook = _OOB_CUSTOM_UPDATE_HOOKS[hid].get(attrname) +# if oob_hook: +# oob_hook[0](obj.typeclass, attrname, value, *oob_hook[1], **oob_hook[2]) +# +# + +# # old cache system +# +# if _ENABLE_LOCAL_CACHES: +# # Cache stores +# _ATTR_CACHE = defaultdict(dict) +# _FIELD_CACHE = defaultdict(dict) +# _PROP_CACHE = defaultdict(dict) +# +# +# def get_cache_sizes(): +# """ +# Get cache sizes, expressed in number of objects and memory size in MB +# """ +# global _ATTR_CACHE, _FIELD_CACHE, _PROP_CACHE +# +# attr_n = sum(len(dic) for dic in _ATTR_CACHE.values()) +# attr_mb = sum(sum(getsizeof(obj) for obj in dic.values()) for dic in _ATTR_CACHE.values()) / 1024.0 +# +# field_n = sum(len(dic) for dic in _FIELD_CACHE.values()) +# field_mb = sum(sum([getsizeof(obj) for obj in dic.values()]) for dic in _FIELD_CACHE.values()) / 1024.0 +# +# prop_n = sum(len(dic) for dic in _PROP_CACHE.values()) +# prop_mb = sum(sum([getsizeof(obj) for obj in dic.values()]) for dic in _PROP_CACHE.values()) / 1024.0 +# +# return (attr_n, attr_mb), (field_n, field_mb), (prop_n, prop_mb) +# +# # on-object database field cache +# def get_field_cache(obj, name): +# "On-model Cache handler." +# global _FIELD_CACHE +# hid = hashid(obj) +# if hid: +# try: +# return _FIELD_CACHE[hid][name] +# except KeyError: +# val = _GA(obj, "db_%s" % name) +# _FIELD_CACHE[hid][name] = val +# return val +# return _GA(obj, "db_%s" % name) +# +# def set_field_cache(obj, name, val): +# "On-model Cache setter. Also updates database." +# _SA(obj, "db_%s" % name, val) +# _GA(obj, "save")() +# hid = hashid(obj) +# if hid: +# global _FIELD_CACHE +# _FIELD_CACHE[hid][name] = val +# # oob hook functionality +# if _OOB_FIELD_UPDATE_HOOKS[hid].get(name): +# _OOB_HANDLER.update(hid, name, val) +# +# def del_field_cache(obj, name): +# "On-model cache deleter" +# hid = hashid(obj) +# _SA(obj, "db_%s" % name, None) +# _GA(obj, "save")() +# if hid: +# try: +# del _FIELD_CACHE[hid][name] +# except KeyError: +# pass +# if _OOB_FIELD_UPDATE_HOOKS[hid].get(name): +# _OOB_HANDLER.update(hid, name, None) +# +# def flush_field_cache(obj=None): +# "On-model cache resetter" +# hid = hashid(obj) +# global _FIELD_CACHE +# if hid: +# try: +# del _FIELD_CACHE[hashid(obj)] +# except KeyError, e: +# pass +# else: +# # clean cache completely +# _FIELD_CACHE = defaultdict(dict) +# +# # on-object property cache (unrelated to database) +# # Note that the get/set_prop_cache handler do not actually +# # get/set the property "on" the object but only reads the +# # value to/from the cache. This is intended to be used +# # with a get/setter property on the object. +# +# def get_prop_cache(obj, name, default=None): +# "On-model Cache handler." +# global _PROP_CACHE +# hid = hashid(obj) +# if hid: +# try: +# val = _PROP_CACHE[hid][name] +# except KeyError: +# return default +# _PROP_CACHE[hid][name] = val +# return val +# return default +# +# def set_prop_cache(obj, name, val): +# "On-model Cache setter. Also updates database." +# hid = hashid(obj) +# if hid: +# global _PROP_CACHE +# _PROP_CACHE[hid][name] = val +# # oob hook functionality +# oob_hook = _OOB_PROP_UPDATE_HOOKS[hid].get(name) +# if oob_hook: +# oob_hook[0](obj.typeclass, name, val, *oob_hook[1], **oob_hook[2]) +# +# +# def del_prop_cache(obj, name): +# "On-model cache deleter" +# try: +# del _PROP_CACHE[hashid(obj)][name] +# except KeyError: +# pass +# def flush_prop_cache(obj=None): +# "On-model cache resetter" +# hid = hashid(obj) +# global _PROP_CACHE +# if hid: +# try: +# del _PROP_CACHE[hid] +# except KeyError,e: +# pass +# else: +# # clean cache completely +# _PROP_CACHE = defaultdict(dict) +# +# # attribute cache +# +# def get_attr_cache(obj, attrname): +# """ +# Attribute cache store +# """ +# return _ATTR_CACHE[hashid(obj)].get(attrname, None) +# +# def set_attr_cache(obj, attrname, attrobj): +# """ +# Cache an attribute object +# """ +# hid = hashid(obj) +# if hid: +# global _ATTR_CACHE +# _ATTR_CACHE[hid][attrname] = attrobj +# # oob hook functionality +# oob_hook = _OOB_ATTR_UPDATE_HOOKS[hid].get(attrname) +# if oob_hook: +# oob_hook[0](obj.typeclass, attrname, attrobj.value, *oob_hook[1], **oob_hook[2]) +# +# def del_attr_cache(obj, attrname): +# """ +# Remove attribute from cache +# """ +# global _ATTR_CACHE +# try: +# _ATTR_CACHE[hashid(obj)][attrname].no_cache = True +# del _ATTR_CACHE[hashid(obj)][attrname] +# except KeyError: +# pass +# +# def flush_attr_cache(obj=None): +# """ +# Flush the attribute cache for this object. +# """ +# global _ATTR_CACHE +# if obj: +# for attrobj in _ATTR_CACHE[hashid(obj)].values(): +# attrobj.no_cache = True +# del _ATTR_CACHE[hashid(obj)] +# else: +# # clean cache completely +# for objcache in _ATTR_CACHE.values(): +# for attrobj in objcache.values(): +# attrobj.no_cache = True +# _ATTR_CACHE = defaultdict(dict) +# +# +# def flush_obj_caches(obj=None): +# "Clean all caches on this object" +# flush_field_cache(obj) +# flush_prop_cache(obj) +# flush_attr_cache(obj) +# + +#else: # local caches disabled. Use simple pass-through replacements - def get_cache_sizes(): - return (0, 0), (0, 0), (0, 0) - def get_field_cache(obj, name): - return _GA(obj, "db_%s" % name) - def set_field_cache(obj, name, val): - _SA(obj, "db_%s" % name, val) - _GA(obj, "save")() - hid = hashid(obj) - if _OOB_FIELD_UPDATE_HOOKS[hid].get(name): - _OOB_HANDLER.update(hid, name, val) - def del_field_cache(obj, name): - _SA(obj, "db_%s" % name, None) - _GA(obj, "save")() - hid = hashid(obj) - if _OOB_FIELD_UPDATE_HOOKS[hid].get(name): - _OOB_HANDLER.update(hid, name, None) - def flush_field_cache(obj=None): - pass - # these should get oob handlers when oob is implemented. - def get_prop_cache(obj, name, default=None): - return None - def set_prop_cache(obj, name, val): - pass - def del_prop_cache(obj, name): - pass - def flush_prop_cache(obj=None): - pass - def get_attr_cache(obj, attrname): - return None - def set_attr_cache(obj, attrname, attrobj): - pass - def del_attr_cache(obj, attrname): - pass - def flush_attr_cache(obj=None): - pass +def get_cache_sizes(): + return (0, 0), (0, 0), (0, 0) +def get_field_cache(obj, name): + return _GA(obj, "db_%s" % name) +def set_field_cache(obj, name, val): + _SA(obj, "db_%s" % name, val) + _GA(obj, "save")() + #hid = hashid(obj) + #if _OOB_FIELD_UPDATE_HOOKS[hid].get(name): + # _OOB_HANDLER.update(hid, name, val) +def del_field_cache(obj, name): + _SA(obj, "db_%s" % name, None) + _GA(obj, "save")() + #hid = hashid(obj) + #if _OOB_FIELD_UPDATE_HOOKS[hid].get(name): + # _OOB_HANDLER.update(hid, name, None) +def flush_field_cache(obj=None): + pass +# these should get oob handlers when oob is implemented. +def get_prop_cache(obj, name, default=None): + return None +def set_prop_cache(obj, name, val): + pass +def del_prop_cache(obj, name): + pass +def flush_prop_cache(obj=None): + pass +def get_attr_cache(obj, attrname): + return None +def set_attr_cache(obj, attrname, attrobj): + pass +def del_attr_cache(obj, attrname): + pass +def flush_attr_cache(obj=None): + pass diff --git a/src/server/server.py b/src/server/server.py index 5492bdecbc..7cc7e685a9 100644 --- a/src/server/server.py +++ b/src/server/server.py @@ -30,6 +30,12 @@ from src.utils.utils import get_evennia_version, mod_import, make_iter from src.comms import channelhandler from src.server.sessionhandler import SESSIONS +# setting up server-side field cache + +from django.db.models.signals import pre_save +from src.server.caches import field_pre_save +pre_save.connect(field_pre_save, dispatch_uid="fieldcache") + _SA = object.__setattr__ if os.name == 'nt': diff --git a/src/settings_default.py b/src/settings_default.py index 745a8c4a62..7237909668 100644 --- a/src/settings_default.py +++ b/src/settings_default.py @@ -159,14 +159,23 @@ DATABASES = { 'HOST':'', 'PORT':'' }} -# Engine Config style for Django versions < 1.2 only. See above. -DATABASE_ENGINE = 'sqlite3' -DATABASE_NAME = os.path.join(GAME_DIR, 'evennia.db3') -DATABASE_USER = '' -DATABASE_PASSWORD = '' -DATABASE_HOST = '' -DATABASE_PORT = '' - +# This manages the object-level caches. Evennia will agressively cache +# fields, properties and attribute lookup. Evennia uses a fast and +# local in-memory cache by default. If a Memcached server is available +# it can be used instead (see django docs). Cache performance can be +# tweaked by adding options to each cache. Finally, any cache can +# be completely turned off by pointing its backend +# to 'django.core.cache.backends.dummy.DummyCache'. +CACHES = { + 'default': { + 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}, + 'field_cache': { + 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}, + 'prop_cache': { + 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}, + 'attr_cache': { + 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}, + } ###################################################################### # Evennia pluggable modules ###################################################################### diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index 931b0e812e..745bc98b01 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -38,11 +38,12 @@ from django.db import models, IntegrityError from django.conf import settings from django.utils.encoding import smart_str from django.contrib.contenttypes.models import ContentType +from django.db.models.fields import AutoField, FieldDoesNotExist from src.utils.idmapper.models import SharedMemoryModel from src.server.caches import get_field_cache, set_field_cache, del_field_cache from src.server.caches import get_attr_cache, set_attr_cache, del_attr_cache from src.server.caches import get_prop_cache, set_prop_cache, del_prop_cache, flush_attr_cache -from src.server.caches import call_ndb_hooks +#from src.server.caches import call_ndb_hooks from src.server.models import ServerConfig from src.typeclasses import managers from src.locks.lockhandler import LockHandler @@ -111,7 +112,7 @@ class Attribute(SharedMemoryModel): # Lock storage db_lock_storage = models.TextField('locks', blank=True) # references the object the attribute is linked to (this is set - # by each child class to this abstact class) + # by each child class to this abstract class) db_obj = None # models.ForeignKey("RefencedObject") # time stamp db_date_created = models.DateTimeField('date_created', editable=False, auto_now_add=True) @@ -455,20 +456,21 @@ class TypedObject(SharedMemoryModel): # 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 get_field_cache(self, "key") - #@key.setter - def __key_set(self, value): - "Setter. Allows for self.key = value" - set_field_cache(self, "key", value) - #@key.deleter - def __key_del(self): - "Deleter. Allows for del self.key" - raise Exception("Cannot delete objectdb key!") - key = property(__key_get, __key_set, __key_del) + #def __key_get(self): + # "Getter. Allows for value = self.key" + # return get_field_cache(self, "key") + ##@key.setter + #def __key_set(self, value): + # "Setter. Allows for self.key = value" + # set_field_cache(self, "key", value) + ##@key.deleter + #def __key_del(self): + # "Deleter. Allows for del self.key" + # raise Exception("Cannot delete objectdb key!") + #key = property(__key_get, __key_set, __key_del) # name property (wraps db_key too - alias to self.key) #@property @@ -1244,7 +1246,7 @@ class TypedObject(SharedMemoryModel): return None def __setattr__(self, key, value): # hook the oob handler here - call_ndb_hooks(self, key, value) + #call_ndb_hooks(self, key, value) _SA(self, key, value) self._ndb_holder = NdbHolder() return self._ndb_holder diff --git a/src/utils/idmapper/base.py b/src/utils/idmapper/base.py index e70f59d8c7..b50598c5a0 100755 --- a/src/utils/idmapper/base.py +++ b/src/utils/idmapper/base.py @@ -8,14 +8,19 @@ Also adds cache_size() for monitoring the size of the cache. """ import os, threading -from twisted.internet import reactor +#from twisted.internet import reactor +#from twisted.internet.threads import blockingCallFromThread from twisted.internet.reactor import callFromThread -from twisted.internet.threads import blockingCallFromThread from django.db.models.base import Model, ModelBase from django.db.models.signals import post_save, pre_delete, post_syncdb from manager import SharedMemoryManager +_GA = object.__getattribute__ +_SA = object.__setattr__ +_DA = object.__delattr__ + + # determine if our current pid is different from the server PID (i.e. # if we are in a subprocess or not) from src import PROC_MODIFIED_OBJS @@ -78,13 +83,39 @@ class SharedMemoryModelBase(ModelBase): if cached_instance is None: cached_instance = new_instance() cls.cache_instance(cached_instance) - return cached_instance + def _prepare(cls): cls.__instance_cache__ = {} #WeakValueDictionary() super(SharedMemoryModelBase, cls)._prepare() + def __init__(cls, *args, **kwargs): + "Takes field names db_* and creates property wrappers named without the db_ prefix. So db_key -> key" + super(SharedMemoryModelBase, cls).__init__(*args, **kwargs) + def create_wrapper(cls, fieldname, wrappername): + "Helper method to create property wrappers with unique names (must be in separate call)" + def _get(cls, fname): + return _GA(cls, fname) + def _set(cls, fname, value): + _SA(cls, fname, value) + _GA(cls, "save")(update_fields=[fname]) # important! + def _del(cls, fname): + raise RuntimeError("You cannot delete field %s on %s; set it to None instead." % (fname, cls)) + type(cls).__setattr__(cls, wrappername, property(lambda cls: _get(cls, fieldname), + lambda cls,val: _set(cls, fieldname, val), + lambda cls: _del(cls, fieldname))) + # eclude some models that should not auto-create wrapper fields + if cls.__name__ in ("ServerConfig", "TypeNick"): + return + # dynamically create the properties + for field in cls._meta.fields: + fieldname = field.name + wrappername = fieldname == "id" and "dbref" or fieldname.replace("db_", "") + if not hasattr(cls, wrappername): + # make sure not to overload manually created wrappers on the model + print "wrapping %s -> %s" % (fieldname, wrappername) + create_wrapper(cls, fieldname, wrappername) class SharedMemoryModel(Model): # CL: setting abstract correctly to allow subclasses to inherit the default @@ -126,6 +157,13 @@ class SharedMemoryModel(Model): return result _get_cache_key = classmethod(_get_cache_key) + def _flush_cached_by_key(cls, key): + try: + del cls.__instance_cache__[key] + except KeyError: + pass + _flush_cached_by_key = classmethod(_flush_cached_by_key) + def get_cached_instance(cls, id): """ Method to retrieve a cached instance by pk value. Returns None when not found @@ -148,13 +186,6 @@ class SharedMemoryModel(Model): return cls.__instance_cache__.values() get_all_cached_instances = classmethod(get_all_cached_instances) - def _flush_cached_by_key(cls, key): - try: - del cls.__instance_cache__[key] - except KeyError: - pass - _flush_cached_by_key = classmethod(_flush_cached_by_key) - def flush_cached_instance(cls, instance): """ Method to flush an instance from the cache. The instance will always be flushed from the cache, @@ -168,7 +199,7 @@ class SharedMemoryModel(Model): flush_instance_cache = classmethod(flush_instance_cache) def save(cls, *args, **kwargs): - "save tracking process/thread issues" + "save method tracking process/thread issues" if _IS_SUBPROCESS: # we keep a store of objects modified in subprocesses so @@ -210,8 +241,6 @@ def update_cached_instance(sender, instance, **kwargs): if not hasattr(instance, 'cache_instance'): return sender.cache_instance(instance) - from src.server.caches import flush_obj_caches - flush_obj_caches(instance) post_save.connect(update_cached_instance) def cache_size(mb=True): From b6383ddab92acbc32b7cbfbe199504f33f133fe6 Mon Sep 17 00:00:00 2001 From: Griatch Date: Wed, 29 May 2013 18:47:51 +0200 Subject: [PATCH 10/49] Moved attr_cache to new caching system, activated all attribute updating signals. --- src/objects/models.py | 7 +++ src/players/models.py | 6 ++ src/scripts/models.py | 6 ++ src/server/caches.py | 115 +++++++++++++++++++------------------ src/typeclasses/models.py | 18 +++--- src/utils/idmapper/base.py | 9 ++- 6 files changed, 95 insertions(+), 66 deletions(-) diff --git a/src/objects/models.py b/src/objects/models.py index a063b256ec..4406902428 100644 --- a/src/objects/models.py +++ b/src/objects/models.py @@ -17,11 +17,13 @@ transparently through the decorating TypeClass. import traceback from django.db import models from django.conf import settings +from django.db.models.signals import post_init, pre_delete from src.utils.idmapper.models import SharedMemoryModel from src.typeclasses.models import Attribute, TypedObject, TypeNick, TypeNickHandler from src.server.caches import get_field_cache, set_field_cache, del_field_cache from src.server.caches import get_prop_cache, set_prop_cache, del_prop_cache +from src.server.caches import attr_post_init, attr_pre_delete from src.typeclasses.typeclass import TypeClass from src.players.models import PlayerNick from src.objects.manager import ObjectManager @@ -53,6 +55,7 @@ _HERE = _("here") # #------------------------------------------------------------ + class ObjAttribute(Attribute): "Attributes for ObjectDB objects." db_obj = models.ForeignKey("ObjectDB") @@ -62,6 +65,10 @@ class ObjAttribute(Attribute): verbose_name = "Object Attribute" verbose_name_plural = "Object Attributes" +# attach the cache handlers for attribute lookup +post_init.connect(attr_post_init, sender=ObjAttribute, dispatch_uid="objattrcache") +pre_delete.connect(attr_pre_delete, sender=ObjAttribute, dispatch_uid="objattrcache") + #------------------------------------------------------------ # # Alias diff --git a/src/players/models.py b/src/players/models.py index 278ab00a14..37e639af18 100644 --- a/src/players/models.py +++ b/src/players/models.py @@ -27,9 +27,12 @@ from django.conf import settings from django.db import models from django.contrib.auth.models import User from django.utils.encoding import smart_str +from django.db.models.signals import post_init, pre_delete from src.server.caches import get_field_cache, set_field_cache, del_field_cache from src.server.caches import get_prop_cache, set_prop_cache, del_prop_cache +from src.server.caches import attr_post_init, attr_pre_delete + from src.players import manager from src.scripts.models import ScriptDB from src.typeclasses.models import Attribute, TypedObject, TypeNick, TypeNickHandler @@ -74,6 +77,9 @@ class PlayerAttribute(Attribute): "Define Django meta options" verbose_name = "Player Attribute" +post_init.connect(attr_post_init, sender=PlayerAttribute, dispatch_uid="playerattrcache") +pre_delete.connect(attr_pre_delete, sender=PlayerAttribute, dispatch_uid="playerattrcache") + #------------------------------------------------------------ # # Player Nicks diff --git a/src/scripts/models.py b/src/scripts/models.py index 538866bca9..ae79794a9a 100644 --- a/src/scripts/models.py +++ b/src/scripts/models.py @@ -26,6 +26,9 @@ Common examples of uses of Scripts: """ from django.conf import settings from django.db import models +from django.db.models.signals import post_init, pre_delete + +from src.server.caches import attr_post_init, attr_pre_delete from src.typeclasses.models import Attribute, TypedObject from django.contrib.contenttypes.models import ContentType from src.scripts.manager import ScriptManager @@ -47,6 +50,9 @@ class ScriptAttribute(Attribute): verbose_name = "Script Attribute" verbose_name_plural = "Script Attributes" +# attach cache handlers for attribute lookup +post_init.connect(attr_post_init, sender=ScriptAttribute, dispatch_uid="scriptattrcache") +pre_delete.connect(attr_pre_delete, sender=ScriptAttribute, dispatch_uid="scriptattrcache") #------------------------------------------------------------ # diff --git a/src/server/caches.py b/src/server/caches.py index d5ad57d6b5..769cbc28b1 100644 --- a/src/server/caches.py +++ b/src/server/caches.py @@ -2,6 +2,8 @@ Central caching module. """ +from django.core.cache import get_cache +#from django.db.models.signals import pre_save, pre_delete, post_init from src.server.models import ServerConfig from src.utils.utils import uses_database, to_str @@ -9,13 +11,27 @@ _GA = object.__getattribute__ _SA = object.__setattr__ _DA = object.__delattr__ +# +# Open handles to the caches +# + +_FIELD_CACHE = get_cache("field_cache") +_ATTR_CACHE = get_cache("attr_cache") + +# make sure caches are empty at startup +_FIELD_CACHE.clear() +_ATTR_CACHE.clear() + +# +# Cache key hash generation +# + if uses_database("mysql") and ServerConfig.objects.get_mysql_db_version() < '5.6.4': # mysql <5.6.4 don't support millisecond precision _DATESTRING = "%Y:%m:%d-%H:%M:%S:000000" else: _DATESTRING = "%Y:%m:%d-%H:%M:%S:%f" - def hashid(obj, suffix=""): """ Returns a per-class unique that combines the object's @@ -49,36 +65,28 @@ def hashid(obj, suffix=""): return to_str(hid) -# signal handlers +# +# Cache callback handlers +# -from django.core.cache import get_cache -#from django.db.models.signals import pre_save, pre_delete, post_init +# Field cache - makes sure to cache all database fields when +# they are saved, no matter from where. -# field cache - -_FIELD_CACHE = get_cache("field_cache") -if not _FIELD_CACHE: - raise RuntimeError("settings.CACHE does not contain a 'field_cache' entry!") - -# callback before saving an object - -def field_pre_save(sender, **kwargs): +# callback to pre_save signal (connected in src.server.server) +def field_pre_save(sender, instance=None, update_fields=None, raw=False, **kwargs): """ Called at the beginning of the save operation. The save method must be called with the update_fields keyword in order to """ - global _FIELD_CACHE - - if kwargs.pop("raw", False): return - instance = kwargs.pop("instance") - fields = kwargs.pop("update_fields", None) - if fields: + if raw: + return + if update_fields: # this is a list of strings at this point. We want field objects - fields = (instance._meta.get_field_by_name(field)[0] for field in fields) + update_fields = (instance._meta.get_field_by_name(field)[0] for field in update_fields) else: # meta.fields are already field objects - fields = instance._meta.fields - for field in fields: + update_fields = instance._meta.fields + for field in update_fields: fieldname = field.name new_value = field.value_from_object(instance) handlername = "_%s_handler" % fieldname @@ -98,39 +106,34 @@ def field_pre_save(sender, **kwargs): # update cache _FIELD_CACHE.set(hid, new_value) -# goes into server: -#pre_save.connect(field_pre_save, dispatch_uid="fieldcache") +# Attr cache - caching the attribute objects related to a given object to +# avoid lookups more than necessary (this makes Attributes en par in speed +# to any property). + +# connected to post_init signal (connected in respective Attribute model) +def attr_post_init(sender, instance=None, **kwargs): + "Called when attribute is created or retrieved in connection with obj." + #print "attr_post_init:", instance, instance.db_obj, instance.db_key + hid = hashid(_GA(instance, "db_obj"), "-%s" % _GA(instance, "db_key")) + if hid: + _ATTR_CACHE.set(hid, sender) +# connected to pre_delete signal (connected in respective Attribute model) +def attr_pre_delete(sender, instance=None, **kwargs): + "Called when attribute is deleted (del_attribute)" + #print "attr_pre_delete:", instance, instance.db_obj, instance.db_key + hid = hashid(_GA(instance, "db_obj"), "-%s" % _GA(instance, "db_key")) + if hid: + #print "attr_pre_delete:", _GA(instance, "db_key") + _ATTR_CACHE.delete(hid) +# access method +def get_attr_cache(obj, attrname): + "Called by get_attribute" + hid = hashid(obj, "-%s" % attrname) + _ATTR_CACHE.delete(hid) + return hid and _ATTR_CACHE.get(hid, None) or None + + -## attr cache - caching the attribute objects related to a given object to -## avoid lookups more than necessary (this makes attributes en par in speed -## to any property). The signal is triggered by the Attribute itself when it -## is created or deleted (it holds a reference to the object) -# -#_ATTR_CACHE = get_cache("attr_cache") -#if not _ATTR_CACHE: -# raise RuntimeError("settings.CACHE does not contain an 'attr_cache' entry!") -# -#def attr_post_init(sender, **kwargs): -# "Called when attribute is created or retrieved in connection with obj." -# hid = hashid(sender.db_obj, "-%s" % sender.db_key) -# _ATTR_CACHE.set(hid, sender) -#def attr_pre_delete(sender, **kwargs): -# "Called when attribute is deleted (del_attribute)" -# hid = hashid(sender.db_obj, "-%s" % sender.db_key) -# _ATTR_CACHE.delete(hid) -# -### goes into server: -#from src.objects.models import ObjAttribute -#from src.scripts.models import ScriptAttribute -#from src.players.models import PlayerAttribute -#post_init.connect(attr_post_init, sender=ObjAttribute, dispatch_uid="objattrcache") -#post_init.connect(attr_post_init, sender=ScriptAttribute, dispatch_uid="scriptattrcache") -#post_init.connect(attr_post_init, sender=PlayerAttribute, dispatch_uid="playerattrcache") -#pre_delete.connect(attr_pre_delete, sender=ObjAttribute, dispatch_uid="objattrcache") -#pre_delete.connect(attr_pre_delete, sender=ScriptAttribute, dispatch_uid="scriptattrcache") -#pre_delete.connect(attr_pre_delete, sender=PlayerAttribute, dispatch_uid="playerattrcache") -# -# ## property cache - this doubles as a central cache and as a way ## to trigger oob on such changes. # @@ -456,8 +459,8 @@ def del_prop_cache(obj, name): pass def flush_prop_cache(obj=None): pass -def get_attr_cache(obj, attrname): - return None +#def get_attr_cache(obj, attrname): +# return None def set_attr_cache(obj, attrname, attrobj): pass def del_attr_cache(obj, attrname): diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index 745bc98b01..79f1da70a8 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -103,7 +103,7 @@ class Attribute(SharedMemoryModel): # Attribute Database Model setup # # - # These databse fields are all set using their corresponding properties, + # These database fields are all set using their corresponding properties, # named same as the field, but withtout the db_* prefix. db_key = models.CharField('key', max_length=255, db_index=True) @@ -933,10 +933,11 @@ class TypedObject(SharedMemoryModel): if not get_attr_cache(self, attribute_name): attrib_obj = _GA(self, "_attribute_class").objects.filter( db_obj=self, db_key__iexact=attribute_name) - if attrib_obj: - set_attr_cache(self, attribute_name, attrib_obj[0]) - else: + if not attrib_obj: return False + #set_attr_cache(self, attribute_name, attrib_obj[0]) + #else: + # return False return True def set_attribute(self, attribute_name, new_value=None, lockstring=""): @@ -953,6 +954,7 @@ class TypedObject(SharedMemoryModel): types checked by secureattr are 'attrread','attredit','attrcreate'. """ attrib_obj = get_attr_cache(self, attribute_name) + print "set_attribute:", attribute_name, attrib_obj if not attrib_obj: attrclass = _GA(self, "_attribute_class") # check if attribute already exists. @@ -975,7 +977,7 @@ class TypedObject(SharedMemoryModel): flush_attr_cache(self) self.delete() raise IntegrityError("Attribute could not be saved - object %s was deleted from database." % self.key) - set_attr_cache(self, attribute_name, attrib_obj) + #set_attr_cache(self, attribute_name, attrib_obj) def get_attribute_obj(self, attribute_name, default=None): """ @@ -987,7 +989,7 @@ class TypedObject(SharedMemoryModel): db_obj=self, db_key__iexact=attribute_name) if not attrib_obj: return default - set_attr_cache(self, attribute_name, attrib_obj[0]) #query is first evaluated here + #set_attr_cache(self, attribute_name, attrib_obj[0]) #query is first evaluated here return attrib_obj[0] return attrib_obj @@ -1006,7 +1008,7 @@ class TypedObject(SharedMemoryModel): db_obj=self, db_key__iexact=attribute_name) if not attrib_obj: return default - set_attr_cache(self, attribute_name, attrib_obj[0]) #query is first evaluated here + #set_attr_cache(self, attribute_name, attrib_obj[0]) #query is first evaluated here return attrib_obj[0].value return attrib_obj.value @@ -1023,7 +1025,7 @@ class TypedObject(SharedMemoryModel): db_obj=self, db_key__iexact=attribute_name) if not attrib_obj: raise AttributeError - set_attr_cache(self, attribute_name, attrib_obj[0]) #query is first evaluated here + #set_attr_cache(self, attribute_name, attrib_obj[0]) #query is first evaluated here return attrib_obj[0].value return attrib_obj.value diff --git a/src/utils/idmapper/base.py b/src/utils/idmapper/base.py index b50598c5a0..6563b220af 100755 --- a/src/utils/idmapper/base.py +++ b/src/utils/idmapper/base.py @@ -91,7 +91,12 @@ class SharedMemoryModelBase(ModelBase): super(SharedMemoryModelBase, cls)._prepare() def __init__(cls, *args, **kwargs): - "Takes field names db_* and creates property wrappers named without the db_ prefix. So db_key -> key" + """ + Takes field names db_* and creates property wrappers named without the db_ prefix. So db_key -> key + This wrapper happens on the class level, so there is no overhead when creating objects. If a class + already has a wrapper of the given name, the automatic creation is skipped. Note: Remember to + document this auto-wrapping in the class header, this could seem very much like magic to the user otherwise. + """ super(SharedMemoryModelBase, cls).__init__(*args, **kwargs) def create_wrapper(cls, fieldname, wrappername): "Helper method to create property wrappers with unique names (must be in separate call)" @@ -114,7 +119,7 @@ class SharedMemoryModelBase(ModelBase): wrappername = fieldname == "id" and "dbref" or fieldname.replace("db_", "") if not hasattr(cls, wrappername): # make sure not to overload manually created wrappers on the model - print "wrapping %s -> %s" % (fieldname, wrappername) + #print "wrapping %s -> %s" % (fieldname, wrappername) create_wrapper(cls, fieldname, wrappername) class SharedMemoryModel(Model): From fb3259be8ce15eb1c80d8e022aa864e1a9825d0d Mon Sep 17 00:00:00 2001 From: Griatch Date: Wed, 29 May 2013 23:07:44 +0200 Subject: [PATCH 11/49] Activated propcache with new cache system. Still not functioning correctly, also the content cache needs to be handled. --- src/objects/models.py | 4 +- src/server/caches.py | 119 +++++++++++++++++++++++-------------- src/typeclasses/models.py | 28 ++++----- src/utils/idmapper/base.py | 2 +- 4 files changed, 87 insertions(+), 66 deletions(-) diff --git a/src/objects/models.py b/src/objects/models.py index 4406902428..f55dd54be6 100644 --- a/src/objects/models.py +++ b/src/objects/models.py @@ -65,7 +65,7 @@ class ObjAttribute(Attribute): verbose_name = "Object Attribute" verbose_name_plural = "Object Attributes" -# attach the cache handlers for attribute lookup +# attach the cache handlers post_init.connect(attr_post_init, sender=ObjAttribute, dispatch_uid="objattrcache") pre_delete.connect(attr_pre_delete, sender=ObjAttribute, dispatch_uid="objattrcache") @@ -248,7 +248,7 @@ class ObjectDB(TypedObject): "Deleter. Allows for del self.aliases" for alias in Alias.objects.filter(db_obj=self): alias.delete() - del_prop_cache(self, "_aliases") + #del_prop_cache(self, "_aliases") aliases = property(__aliases_get, __aliases_set, __aliases_del) # player property (wraps db_player) diff --git a/src/server/caches.py b/src/server/caches.py index 769cbc28b1..27d2b5574c 100644 --- a/src/server/caches.py +++ b/src/server/caches.py @@ -2,6 +2,7 @@ Central caching module. """ +from django.dispatch import Signal from django.core.cache import get_cache #from django.db.models.signals import pre_save, pre_delete, post_init from src.server.models import ServerConfig @@ -17,14 +18,16 @@ _DA = object.__delattr__ _FIELD_CACHE = get_cache("field_cache") _ATTR_CACHE = get_cache("attr_cache") +_PROP_CACHE = get_cache("prop_cache") # make sure caches are empty at startup _FIELD_CACHE.clear() _ATTR_CACHE.clear() +_PROP_CACHE.clear() -# +#------------------------------------------------------------ # Cache key hash generation -# +#------------------------------------------------------------ if uses_database("mysql") and ServerConfig.objects.get_mysql_db_version() < '5.6.4': # mysql <5.6.4 don't support millisecond precision @@ -58,19 +61,23 @@ def hashid(obj, suffix=""): if not idnum or not date: # this will happen if setting properties on an object which is not yet saved return None - # build the hashid - hid = "%s-%s-#%s%s" % (_GA(obj, "__class__"), date, idnum, suffix) - hid = hid.replace(" ", "") + hid = "%s-%s-#%s" % (_GA(obj, "__class__"), date, idnum) + hid = hid.replace(" ", "") # we have to remove the class-name's space, for memcached's sake + # we cache the object part of the hashid to avoid too many object lookups _SA(obj, "_hashid", hid) + # build the complete hashid + hid = "%s%s" % (hid, suffix) return to_str(hid) -# +#------------------------------------------------------------ # Cache callback handlers -# +#------------------------------------------------------------ +#------------------------------------------------------------ # Field cache - makes sure to cache all database fields when # they are saved, no matter from where. +#------------------------------------------------------------ # callback to pre_save signal (connected in src.server.server) def field_pre_save(sender, instance=None, update_fields=None, raw=False, **kwargs): @@ -106,9 +113,18 @@ def field_pre_save(sender, instance=None, update_fields=None, raw=False, **kwarg # update cache _FIELD_CACHE.set(hid, new_value) +# access method + +def flush_field_cache(): + "Clear the field cache" + _FIELD_CACHE.clear() + + +#------------------------------------------------------------ # Attr cache - caching the attribute objects related to a given object to # avoid lookups more than necessary (this makes Attributes en par in speed # to any property). +#------------------------------------------------------------ # connected to post_init signal (connected in respective Attribute model) def attr_post_init(sender, instance=None, **kwargs): @@ -117,6 +133,7 @@ def attr_post_init(sender, instance=None, **kwargs): hid = hashid(_GA(instance, "db_obj"), "-%s" % _GA(instance, "db_key")) if hid: _ATTR_CACHE.set(hid, sender) + # connected to pre_delete signal (connected in respective Attribute model) def attr_pre_delete(sender, instance=None, **kwargs): "Called when attribute is deleted (del_attribute)" @@ -125,42 +142,52 @@ def attr_pre_delete(sender, instance=None, **kwargs): if hid: #print "attr_pre_delete:", _GA(instance, "db_key") _ATTR_CACHE.delete(hid) -# access method + +# access methods + def get_attr_cache(obj, attrname): "Called by get_attribute" hid = hashid(obj, "-%s" % attrname) _ATTR_CACHE.delete(hid) return hid and _ATTR_CACHE.get(hid, None) or None +def set_attr_cache(attrobj): + "Set the attr cache manually; this can be used to update" + attr_post_init(None, instance=attrobj) +def flush_attr_cache(): + "Clear attribute cache" + _ATTR_CACHE.clear() -## property cache - this doubles as a central cache and as a way -## to trigger oob on such changes. -# -#from django.dispatch import Signal -#_PROP_CACHE = get_cache("prop_cache") -#if not _PROP_CACHE: -# raise RuntimeError("settings.CACHE does not contain a 'prop_cache' entry!") -# -#PROP_POST_UPDATE = Signal(providing_args=["propname", "propvalue"]) -# -#def prop_update(sender, **kwargs): -# "Called when a propery is updated. kwargs are propname and propvalue." -# propname, propvalue = kwargs.pop("propname", None), kwargs.pop("propvalue", None) -# if propname == None: return -# hid = hashid(sender, "-%s" % propname) -# _PROP_CACHE.set(hid, propvalue) -# -#PROP_POST_UPDATE.connect(prop_update, dispatch_uid="propcache") -# -# - - +#------------------------------------------------------------ +# Property cache - this is a generic cache for properties stored on models. +#------------------------------------------------------------ +# access methods +def get_prop_cache(obj, propname): + "retrieve data from cache" + hid = hashid(obj, "-%s" % propname) + if hid: + #print "get_prop_cache", hid, propname, _PROP_CACHE.get(hid, None) + return _PROP_CACHE.get(hid, None) +def set_prop_cache(obj, propname, propvalue): + "Set property cache" + hid = hashid(obj, "-%s" % propname) + if hid: + #print "set_prop_cache", propname, propvalue + _PROP_CACHE.set(hid, propvalue) +def del_prop_cache(obj, propname): + "Delete element from property cache" + hid = hashid(obj, "-%s" % propname) + if hid: + _PROP_CACHE.delete(hid) +def flush_prop_cache(): + "Clear property cache" + _PROP_CACHE.clear() #_ENABLE_LOCAL_CACHES = settings.GAME_CACHE_TYPE @@ -448,23 +475,23 @@ def del_field_cache(obj, name): #hid = hashid(obj) #if _OOB_FIELD_UPDATE_HOOKS[hid].get(name): # _OOB_HANDLER.update(hid, name, None) -def flush_field_cache(obj=None): - pass +#def flush_field_cache(obj=None): +# pass # these should get oob handlers when oob is implemented. -def get_prop_cache(obj, name, default=None): - return None -def set_prop_cache(obj, name, val): - pass -def del_prop_cache(obj, name): - pass -def flush_prop_cache(obj=None): - pass +#def get_prop_cache(obj, name, default=None): +# return None +#def set_prop_cache(obj, name, val): +# pass +#def del_prop_cache(obj, name): +# pass +#def flush_prop_cache(obj=None): +# pass #def get_attr_cache(obj, attrname): # return None -def set_attr_cache(obj, attrname, attrobj): - pass -def del_attr_cache(obj, attrname): - pass -def flush_attr_cache(obj=None): - pass +#def set_attr_cache(obj, attrname, attrobj): +# pass +#def del_attr_cache(obj, attrname): +# pass +#def flush_attr_cache(obj=None): +# pass diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index 79f1da70a8..24696c7881 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -41,7 +41,7 @@ from django.contrib.contenttypes.models import ContentType from django.db.models.fields import AutoField, FieldDoesNotExist from src.utils.idmapper.models import SharedMemoryModel from src.server.caches import get_field_cache, set_field_cache, del_field_cache -from src.server.caches import get_attr_cache, set_attr_cache, del_attr_cache +from src.server.caches import get_attr_cache, set_attr_cache from src.server.caches import get_prop_cache, set_prop_cache, del_prop_cache, flush_attr_cache #from src.server.caches import call_ndb_hooks from src.server.models import ServerConfig @@ -60,8 +60,6 @@ _CTYPEGET = ContentType.objects.get _GA = object.__getattribute__ _SA = object.__setattr__ _DA = object.__delattr__ -#_PLOADS = pickle.loads -#_PDUMPS = pickle.dumps #------------------------------------------------------------ # @@ -933,11 +931,10 @@ class TypedObject(SharedMemoryModel): if not get_attr_cache(self, attribute_name): attrib_obj = _GA(self, "_attribute_class").objects.filter( db_obj=self, db_key__iexact=attribute_name) - if not attrib_obj: + if attrib_obj: + set_attr_cache(attrib_obj[0]) + else: return False - #set_attr_cache(self, attribute_name, attrib_obj[0]) - #else: - # return False return True def set_attribute(self, attribute_name, new_value=None, lockstring=""): @@ -954,7 +951,6 @@ class TypedObject(SharedMemoryModel): types checked by secureattr are 'attrread','attredit','attrcreate'. """ attrib_obj = get_attr_cache(self, attribute_name) - print "set_attribute:", attribute_name, attrib_obj if not attrib_obj: attrclass = _GA(self, "_attribute_class") # check if attribute already exists. @@ -963,8 +959,9 @@ class TypedObject(SharedMemoryModel): if attrib_obj: # use old attribute attrib_obj = attrib_obj[0] + set_attr_cache(attrib_obj) # renew cache else: - # no match; create new attribute + # no match; create new attribute (this will cache automatically) attrib_obj = attrclass(db_key=attribute_name, db_obj=self) if lockstring: attrib_obj.locks.add(lockstring) @@ -977,7 +974,6 @@ class TypedObject(SharedMemoryModel): flush_attr_cache(self) self.delete() raise IntegrityError("Attribute could not be saved - object %s was deleted from database." % self.key) - #set_attr_cache(self, attribute_name, attrib_obj) def get_attribute_obj(self, attribute_name, default=None): """ @@ -989,7 +985,7 @@ class TypedObject(SharedMemoryModel): db_obj=self, db_key__iexact=attribute_name) if not attrib_obj: return default - #set_attr_cache(self, attribute_name, attrib_obj[0]) #query is first evaluated here + set_attr_cache(attrib_obj[0]) #query is first evaluated here return attrib_obj[0] return attrib_obj @@ -1008,7 +1004,7 @@ class TypedObject(SharedMemoryModel): db_obj=self, db_key__iexact=attribute_name) if not attrib_obj: return default - #set_attr_cache(self, attribute_name, attrib_obj[0]) #query is first evaluated here + set_attr_cache(attrib_obj[0]) #query is first evaluated here return attrib_obj[0].value return attrib_obj.value @@ -1025,7 +1021,7 @@ class TypedObject(SharedMemoryModel): db_obj=self, db_key__iexact=attribute_name) if not attrib_obj: raise AttributeError - #set_attr_cache(self, attribute_name, attrib_obj[0]) #query is first evaluated here + set_attr_cache(attrib_obj[0]) #query is first evaluated here return attrib_obj[0].value return attrib_obj.value @@ -1037,8 +1033,7 @@ class TypedObject(SharedMemoryModel): """ attr_obj = get_attr_cache(self, attribute_name) if attr_obj: - del_attr_cache(self, attribute_name) - attr_obj.delete() + attr_obj.delete() # this will clear attr cache automatically else: try: _GA(self, "_attribute_class").objects.filter( @@ -1055,8 +1050,7 @@ class TypedObject(SharedMemoryModel): """ attr_obj = get_attr_cache(self, attribute_name) if attr_obj: - del_attr_cache(self, attribute_name) - attr_obj.delete() + attr_obj.delete() # this will clear attr cache automatically else: try: _GA(self, "_attribute_class").objects.filter( diff --git a/src/utils/idmapper/base.py b/src/utils/idmapper/base.py index 6563b220af..30b22d1cd1 100755 --- a/src/utils/idmapper/base.py +++ b/src/utils/idmapper/base.py @@ -116,7 +116,7 @@ class SharedMemoryModelBase(ModelBase): # dynamically create the properties for field in cls._meta.fields: fieldname = field.name - wrappername = fieldname == "id" and "dbref" or fieldname.replace("db_", "") + wrappername = fieldname == "id" and "dbid" or fieldname.replace("db_", "") if not hasattr(cls, wrappername): # make sure not to overload manually created wrappers on the model #print "wrapping %s -> %s" % (fieldname, wrappername) From 41235c25a2c20109e42530ae80e115a8fc12100e Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 30 May 2013 00:49:47 +0200 Subject: [PATCH 12/49] Changed propcache back to a simple dict. Working on content cache, not working yet. --- src/objects/models.py | 131 ++++++++++++++++++++++++++------------ src/server/caches.py | 25 +++++--- src/typeclasses/models.py | 18 +++--- 3 files changed, 114 insertions(+), 60 deletions(-) diff --git a/src/objects/models.py b/src/objects/models.py index f55dd54be6..8237bd0da2 100644 --- a/src/objects/models.py +++ b/src/objects/models.py @@ -306,27 +306,16 @@ class ObjectDB(TypedObject): del_field_cache(self, "sessid") sessid = property(__sessid_get, __sessid_set, __sessid_del) - # location property (wraps db_location) - #@property - def __location_get(self): - "Getter. Allows for value = self.location." - loc = get_field_cache(self, "location") - if loc: - return _GA(loc, "typeclass") - return None - #@location.setter - def __location_set(self, location): - "Setter. Allows for self.location = location" + def _db_location_handler(self, new_value, old_value=None): + "This handles changes to the db_location field." + print "db_location_handler:", new_value, old_value try: - old_loc = _GA(self, "location") - if ObjectDB.objects.dbref(location): - # dbref search - loc = ObjectDB.objects.dbref_search(location) - loc = loc and _GA(loc, "dbobj") - elif location and type(location) != ObjectDB: - loc = _GA(location, "dbobj") - else: - loc = location + old_loc = old_value + # new_value can be dbref, typeclass or dbmodel + if ObjectDB.objects.dbref(new_value, reqhash=False): + loc = ObjectDB.objects.dbref_search(new_value) + # this should not fail if new_value is valid. + loc = _GA(loc, "dbobj") # recursive location check def is_loc_loop(loc, depth=0): @@ -340,32 +329,85 @@ class ObjectDB(TypedObject): except RuntimeWarning: pass # set the location - set_field_cache(self, "location", loc) + _SA(self, "db_location", loc) # update the contents of each location if old_loc: - _GA(_GA(old_loc, "dbobj"), "contents_update")() + _GA(_GA(old_loc, "dbobj"), "contents_update")(self, remove=True) if loc: - _GA(loc, "contents_update")() + _GA(loc, "contents_update")(self) except RuntimeError: string = "Cannot set location, " - string += "%s.location = %s would create a location-loop." % (self.key, loc) + string += "%s.location = %s would create a location-loop." % (self.key, new_value) _GA(self, "msg")(_(string)) logger.log_trace(string) raise RuntimeError(string) except Exception, e: string = "Cannot set location (%s): " % str(e) - string += "%s is not a valid location." % location + string += "%s is not a valid location." % new_value _GA(self, "msg")(_(string)) logger.log_trace(string) raise Exception(string) - #@location.deleter - def __location_del(self): - "Deleter. Allows for del self.location" - _GA(self, "location").contents_update() - _SA(self, "db_location", None) - _GA(self, "save")() - del_field_cache(self, "location") - location = property(__location_get, __location_set, __location_del) + + ## location property (wraps db_location) + ##@property + #def __location_get(self): + # "Getter. Allows for value = self.location." + # loc = get_field_cache(self, "location") + # if loc: + # return _GA(loc, "typeclass") + # return None + ##@location.setter + #def __location_set(self, location): + # "Setter. Allows for self.location = location" + # try: + # old_loc = _GA(self, "location") + # if ObjectDB.objects.dbref(location): + # # dbref search + # loc = ObjectDB.objects.dbref_search(location) + # loc = loc and _GA(loc, "dbobj") + # elif location and type(location) != ObjectDB: + # loc = _GA(location, "dbobj") + # else: + # loc = location + + # # recursive location check + # def is_loc_loop(loc, depth=0): + # "Recursively traverse the target location to make sure we are not in it." + # if depth > 10: return + # elif loc == self: raise RuntimeError + # elif loc == None: raise RuntimeWarning # just to quickly get out + # return is_loc_loop(_GA(loc, "db_location"), depth+1) + # # check so we don't create a location loop - if so, RuntimeError will be raised. + # try: is_loc_loop(loc) + # except RuntimeWarning: pass + + # # set the location + # set_field_cache(self, "location", loc) + # # update the contents of each location + # if old_loc: + # _GA(_GA(old_loc, "dbobj"), "contents_update")() + # if loc: + # _GA(loc, "contents_update")() + # except RuntimeError: + # string = "Cannot set location, " + # string += "%s.location = %s would create a location-loop." % (self.key, loc) + # _GA(self, "msg")(_(string)) + # logger.log_trace(string) + # raise RuntimeError(string) + # except Exception, e: + # string = "Cannot set location (%s): " % str(e) + # string += "%s is not a valid location." % location + # _GA(self, "msg")(_(string)) + # logger.log_trace(string) + # raise Exception(string) + ##@location.deleter + #def __location_del(self): + # "Deleter. Allows for del self.location" + # _GA(self, "location").contents_update() + # _SA(self, "db_location", None) + # _GA(self, "save")() + # del_field_cache(self, "location") + #location = property(__location_get, __location_set, __location_del) # home property (wraps db_home) #@property @@ -522,19 +564,26 @@ class ObjectDB(TypedObject): exclude = make_iter(exclude) if cont == None: cont = _GA(self, "contents_update")() - return [obj for obj in cont if obj not in exclude] + return [obj for obj in cont.values() if obj not in exclude] contents = property(contents_get) - def contents_update(self): + def contents_update(self, obj=None, remove=False): """ - Updates the contents property of the object with a new - object Called by - self.location_set. + Updates the contents property of the object - obj - - remove (true/false) - remove obj from content list + add - object to add to content list + remove object to remove from content list """ - cont = ObjectDB.objects.get_contents(self) + cont = get_prop_cache(self, "_contents") + if not cont: + cont = {} + if obj: + if remove: + cont.pop(self.dbid, None) + else: + cont[self.dbid] = obj + else: + cont = dict((o.dbid, o) for o in ObjectDB.objects.get_contents(self)) set_prop_cache(self, "_contents", cont) return cont diff --git a/src/server/caches.py b/src/server/caches.py index 27d2b5574c..9cbeb5bf4e 100644 --- a/src/server/caches.py +++ b/src/server/caches.py @@ -2,6 +2,8 @@ Central caching module. """ + +from collections import defaultdict from django.dispatch import Signal from django.core.cache import get_cache #from django.db.models.signals import pre_save, pre_delete, post_init @@ -18,12 +20,13 @@ _DA = object.__delattr__ _FIELD_CACHE = get_cache("field_cache") _ATTR_CACHE = get_cache("attr_cache") -_PROP_CACHE = get_cache("prop_cache") +#_PROP_CACHE = get_cache("prop_cache") +_PROP_CACHE = defaultdict(dict) # make sure caches are empty at startup _FIELD_CACHE.clear() _ATTR_CACHE.clear() -_PROP_CACHE.clear() +#_PROP_CACHE.clear() #------------------------------------------------------------ # Cache key hash generation @@ -106,7 +109,7 @@ def field_pre_save(sender, instance=None, update_fields=None, raw=False, **kwarg old_value = _FIELD_CACHE.get(hid) if hid else None # the handler may modify the stored value in various ways # don't catch exceptions, the handler must work! - new_value = handler(instance, new_value, oldval=old_value) + new_value = handler(new_value, old_value=old_value) # we re-assign this to the field, save() will pick it up from there _SA(instance, fieldname, new_value) if hid: @@ -170,24 +173,28 @@ def get_prop_cache(obj, propname): hid = hashid(obj, "-%s" % propname) if hid: #print "get_prop_cache", hid, propname, _PROP_CACHE.get(hid, None) - return _PROP_CACHE.get(hid, None) + return _PROP_CACHE[hid].get(propname, None) def set_prop_cache(obj, propname, propvalue): "Set property cache" hid = hashid(obj, "-%s" % propname) if hid: #print "set_prop_cache", propname, propvalue - _PROP_CACHE.set(hid, propvalue) + _PROP_CACHE[hid][propname] = propvalue + #_PROP_CACHE.set(hid, propvalue) def del_prop_cache(obj, propname): "Delete element from property cache" hid = hashid(obj, "-%s" % propname) - if hid: - _PROP_CACHE.delete(hid) + if hid and propname in _PROP_CACHE[hid]: + del _PROP_CACHE[hid][propname] + #_PROP_CACHE.delete(hid) def flush_prop_cache(): "Clear property cache" - _PROP_CACHE.clear() + global _PROP_CACHE + _PROP_CACHE = defaultdict(dict) + #_PROP_CACHE.clear() #_ENABLE_LOCAL_CACHES = settings.GAME_CACHE_TYPE @@ -491,7 +498,7 @@ def del_field_cache(obj, name): #def set_attr_cache(obj, attrname, attrobj): # pass #def del_attr_cache(obj, attrname): -# pass +# passk #def flush_attr_cache(obj=None): # pass diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index 24696c7881..a39860b898 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -474,34 +474,32 @@ class TypedObject(SharedMemoryModel): #@property def __name_get(self): "Getter. Allows for value = self.name" - return get_field_cache(self, "key") - #@name.setter + return self.key + #@name.sette def __name_set(self, value): "Setter. Allows for self.name = value" - set_field_cache(self, "key", value) + self.key = value #@name.deleter def __name_del(self): "Deleter. Allows for del self.name" raise Exception("Cannot delete name!") name = property(__name_get, __name_set, __name_del) - # typeclass_path property + # typeclass_path property - we don't cache this. #@property def __typeclass_path_get(self): "Getter. Allows for value = self.typeclass_path" - return get_field_cache(self, "typeclass_path") + return _GA(self, "db_typeclass_path")#get_field_cache(self, "typeclass_path") #@typeclass_path.setter def __typeclass_path_set(self, value): "Setter. Allows for self.typeclass_path = value" - set_field_cache(self, "typeclass_path", value) - _SA(self, "_cached_typeclass", None) + _SA(self, "db_typeclass_path", value) + _GA(self, "save")(update_fields=["db_typeclass_path"]) #@typeclass_path.deleter def __typeclass_path_del(self): "Deleter. Allows for del self.typeclass_path" self.db_typeclass_path = "" - self.save() - del_field_cache(self, "typeclass_path") - _SA(self, "_cached_typeclass", None) + _GA(self, "save")(update_fields=["db_typeclass_path"]) typeclass_path = property(__typeclass_path_get, __typeclass_path_set, __typeclass_path_del) # date_created property From 7351aacba5a1429424a6b59dc057cf20e72585f3 Mon Sep 17 00:00:00 2001 From: Griatch Date: Wed, 5 Jun 2013 18:47:41 +0200 Subject: [PATCH 13/49] Fixed an issue with setting location. Still errors with creating new objects. --- src/objects/models.py | 29 +++++++++++++------------- src/server/caches.py | 1 + src/typeclasses/models.py | 3 ++- src/utils/idmapper/base.py | 42 ++++++++++++++++++++++++++++++-------- src/utils/utils.py | 26 +++++++++++------------ 5 files changed, 64 insertions(+), 37 deletions(-) diff --git a/src/objects/models.py b/src/objects/models.py index 8237bd0da2..907feb5945 100644 --- a/src/objects/models.py +++ b/src/objects/models.py @@ -178,9 +178,10 @@ class ObjectDB(TypedObject): # db_key (also 'name' works), db_typeclass_path, db_date_created, # db_permissions # - # These databse fields (including the inherited ones) are all set - # using their corresponding properties, named same as the field, - # but withtout the db_* prefix. + # These databse fields (including the inherited ones) should normally be set + # using their corresponding wrapper properties, named same as the field, but without + # the db_* prefix (e.g. the db_key field is set with self.key instead). The wrappers + # will automatically save and cache the data more efficiently. # If this is a character object, the player is connected here. db_player = models.ForeignKey("players.PlayerDB", blank=True, null=True, verbose_name='player', @@ -217,7 +218,6 @@ class ObjectDB(TypedObject): _GA(self, "cmdset").update(init_mode=True) _SA(self, "scripts", ScriptHandler(self)) _SA(self, "nicks", ObjectNickHandler(self)) - # store the attribute class # Wrapper properties to easily set database fields. These are # @property decorators that allows to access these fields using @@ -306,16 +306,17 @@ class ObjectDB(TypedObject): del_field_cache(self, "sessid") sessid = property(__sessid_get, __sessid_set, __sessid_del) - def _db_location_handler(self, new_value, old_value=None): + def _db_location_handler(self, loc, old_value=None): "This handles changes to the db_location field." - print "db_location_handler:", new_value, old_value + #print "db_location_handler:", loc, old_value try: old_loc = old_value # new_value can be dbref, typeclass or dbmodel - if ObjectDB.objects.dbref(new_value, reqhash=False): - loc = ObjectDB.objects.dbref_search(new_value) - # this should not fail if new_value is valid. - loc = _GA(loc, "dbobj") + if ObjectDB.objects.dbref(loc, reqhash=False): + loc = ObjectDB.objects.dbref_search(loc) + if loc and type(loc) != ObjectDB: + # this should not fail if new_value is valid. + loc = _GA(loc, "dbobj") # recursive location check def is_loc_loop(loc, depth=0): @@ -328,22 +329,22 @@ class ObjectDB(TypedObject): try: is_loc_loop(loc) except RuntimeWarning: pass - # set the location - _SA(self, "db_location", loc) + #print "db_location_handler2:", _GA(loc, "db_key") if loc else loc, type(loc) # update the contents of each location if old_loc: _GA(_GA(old_loc, "dbobj"), "contents_update")(self, remove=True) if loc: _GA(loc, "contents_update")(self) + return loc except RuntimeError: string = "Cannot set location, " - string += "%s.location = %s would create a location-loop." % (self.key, new_value) + string += "%s.location = %s would create a location-loop." % (self.key, loc) _GA(self, "msg")(_(string)) logger.log_trace(string) raise RuntimeError(string) except Exception, e: string = "Cannot set location (%s): " % str(e) - string += "%s is not a valid location." % new_value + string += "%s is not a valid location." % loc _GA(self, "msg")(_(string)) logger.log_trace(string) raise Exception(string) diff --git a/src/server/caches.py b/src/server/caches.py index 9cbeb5bf4e..c933d46c19 100644 --- a/src/server/caches.py +++ b/src/server/caches.py @@ -90,6 +90,7 @@ def field_pre_save(sender, instance=None, update_fields=None, raw=False, **kwarg """ if raw: return + print "field_pre_save:", _GA(instance, "db_key") if hasattr(instance, "db_key") else instance, update_fields if update_fields: # this is a list of strings at this point. We want field objects update_fields = (instance._meta.get_field_by_name(field)[0] for field in update_fields) diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index a39860b898..85cdad472d 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -436,7 +436,8 @@ class TypedObject(SharedMemoryModel): def __init__(self, *args, **kwargs): "We must initialize the parent first - important!" SharedMemoryModel.__init__(self, *args, **kwargs) - self.locks = LockHandler(self) + _SA(self, "dbobj", self) # this allows for self-reference + _SA(self, "locks", LockHandler(self)) class Meta: """ diff --git a/src/utils/idmapper/base.py b/src/utils/idmapper/base.py index 30b22d1cd1..a1b7d1d770 100755 --- a/src/utils/idmapper/base.py +++ b/src/utils/idmapper/base.py @@ -11,8 +11,10 @@ import os, threading #from twisted.internet import reactor #from twisted.internet.threads import blockingCallFromThread from twisted.internet.reactor import callFromThread +from django.core.exceptions import ObjectDoesNotExist from django.db.models.base import Model, ModelBase from django.db.models.signals import post_save, pre_delete, post_syncdb +from src.utils.utils import dbref from manager import SharedMemoryManager @@ -92,6 +94,7 @@ class SharedMemoryModelBase(ModelBase): def __init__(cls, *args, **kwargs): """ + Field shortcut creation: Takes field names db_* and creates property wrappers named without the db_ prefix. So db_key -> key This wrapper happens on the class level, so there is no overhead when creating objects. If a class already has a wrapper of the given name, the automatic creation is skipped. Note: Remember to @@ -101,24 +104,47 @@ class SharedMemoryModelBase(ModelBase): def create_wrapper(cls, fieldname, wrappername): "Helper method to create property wrappers with unique names (must be in separate call)" def _get(cls, fname): - return _GA(cls, fname) + "Wrapper for getting database field" + value = _GA(cls, fname) + if hasattr(value, "typeclass"): + return _GA(value, "typeclass") + #print "_get wrapper:", fname, value, type(value) + return value def _set(cls, fname, value): + "Wrapper for setting database field" + if hasattr(value, "dbobj"): + value = _GA(value, "dbobj") + else: + # we also allow setting using dbrefs, if so we try to load the matching object. + # (we assume the object is of the same type as the class holding the field, if + # not a custom handler must be used for that field) + dbid = dbref(value, reqhash=False) + if dbid: + try: + value = cls._default_manager.get(id=dbid) + except ObjectDoesNotExist: + err = "Could not set %s. Tried to treat value '%s' as a dbref, but no matching object with that id was found." + err = err % (fname, value) + raise ObjectDoesNotExist(err) + print "_set wrapper:", fname, value, type(value) _SA(cls, fname, value) - _GA(cls, "save")(update_fields=[fname]) # important! + _GA(cls, "save")(update_fields=[fname]) # important - this saves one field only def _del(cls, fname): + "Wrapper for clearing database field" raise RuntimeError("You cannot delete field %s on %s; set it to None instead." % (fname, cls)) - type(cls).__setattr__(cls, wrappername, property(lambda cls: _get(cls, fieldname), - lambda cls,val: _set(cls, fieldname, val), - lambda cls: _del(cls, fieldname))) - # eclude some models that should not auto-create wrapper fields + type(cls).__setattr__(cls, wrappername, property(fget=lambda cls: _get(cls, fieldname), + fset=lambda cls,val: _set(cls, fieldname, val), + fdel=lambda cls: _del(cls, fieldname), + doc="Wraps setting, saving and caching the %s field." % fieldname)) + # exclude some models that should not auto-create wrapper fields if cls.__name__ in ("ServerConfig", "TypeNick"): return - # dynamically create the properties + # dynamically create the wrapper properties for all fields not already handled for field in cls._meta.fields: fieldname = field.name wrappername = fieldname == "id" and "dbid" or fieldname.replace("db_", "") if not hasattr(cls, wrappername): - # make sure not to overload manually created wrappers on the model + # makes sure not to overload manually created wrappers on the model #print "wrapping %s -> %s" % (fieldname, wrappername) create_wrapper(cls, fieldname, wrappername) diff --git a/src/utils/utils.py b/src/utils/utils.py index 503516e5f8..75b52b89ea 100644 --- a/src/utils/utils.py +++ b/src/utils/utils.py @@ -287,22 +287,20 @@ def pypath_to_realpath(python_path, file_ending='.py'): def dbref(dbref, reqhash=True): """ - Converts/checks if input is a valid dbref Valid forms of dbref - (database reference number) are either a string '#N' or - an integer N. Output is the integer part. + Converts/checks if input is a valid dbref. + If reqhash is set, only input strings on the form '#N', where N is an integer + is accepted. Otherwise strings '#N', 'N' and integers N are all accepted. + Output is the integer part. """ - if reqhash and not (isinstance(dbref, basestring) and dbref.startswith("#")): - return None - if isinstance(dbref, basestring): + if reqhash: + return (int(dbref.lstrip('#')) if (isinstance(dbref, basestring) and + dbref.startswith("#") and + dbref.lstrip('#').isdigit()) + else None) + elif isinstance(dbref, basestring): dbref = dbref.lstrip('#') - try: - dbref = int(dbref) - if dbref < 1: - return None - except Exception: - return None - return dbref - return None + return int(dbref) if dbref.isdigit() else None + return dbref if isinstance(dbref, int) else None def to_unicode(obj, encoding='utf-8', force_string=False): """ From a0a94df83d3e68e78776f8db403bf801dc41586d Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 6 Jun 2013 12:45:39 +0200 Subject: [PATCH 14/49] Removed extra caching for fields (this slowed things down over normal django field caching). Considering reworking Attribute storage in order to make use of those caches as well. --- src/server/caches.py | 52 +++++++++++++++++++++++++------------- src/typeclasses/models.py | 11 ++++++-- src/utils/idmapper/base.py | 34 +++++++++++++++++-------- 3 files changed, 66 insertions(+), 31 deletions(-) diff --git a/src/server/caches.py b/src/server/caches.py index c933d46c19..a3d123b2bd 100644 --- a/src/server/caches.py +++ b/src/server/caches.py @@ -18,13 +18,14 @@ _DA = object.__delattr__ # Open handles to the caches # -_FIELD_CACHE = get_cache("field_cache") -_ATTR_CACHE = get_cache("attr_cache") +#_FIELD_CACHE = get_cache("field_cache") +_ATTR_CACHE = {} +#_ATTR_CACHE = get_cache("attr_cache") #_PROP_CACHE = get_cache("prop_cache") _PROP_CACHE = defaultdict(dict) # make sure caches are empty at startup -_FIELD_CACHE.clear() +#_FIELD_CACHE.clear() _ATTR_CACHE.clear() #_PROP_CACHE.clear() @@ -93,10 +94,10 @@ def field_pre_save(sender, instance=None, update_fields=None, raw=False, **kwarg print "field_pre_save:", _GA(instance, "db_key") if hasattr(instance, "db_key") else instance, update_fields if update_fields: # this is a list of strings at this point. We want field objects - update_fields = (instance._meta.get_field_by_name(field)[0] for field in update_fields) + update_fields = (_GA(_GA(instance, "_meta"), "get_field_by_name")(field)[0] for field in update_fields) else: # meta.fields are already field objects - update_fields = instance._meta.fields + update_fields = _GA(_GA(instance, "_meta"), "fields") for field in update_fields: fieldname = field.name new_value = field.value_from_object(instance) @@ -105,23 +106,33 @@ def field_pre_save(sender, instance=None, update_fields=None, raw=False, **kwarg handler = _GA(instance, handlername) except AttributeError: handler = None - hid = hashid(instance, "-%s" % fieldname) + #hid = hashid(instance, "-%s" % fieldname) if callable(handler): - old_value = _FIELD_CACHE.get(hid) if hid else None + old_value = _GA(instance, _GA(field, "get_cache_name")())#_FIELD_CACHE.get(hid) if hid else None # the handler may modify the stored value in various ways # don't catch exceptions, the handler must work! new_value = handler(new_value, old_value=old_value) # we re-assign this to the field, save() will pick it up from there _SA(instance, fieldname, new_value) - if hid: - # update cache - _FIELD_CACHE.set(hid, new_value) + #if hid: + # # update cache + # _FIELD_CACHE.set(hid, new_value) # access method - -def flush_field_cache(): - "Clear the field cache" - _FIELD_CACHE.clear() +# +#def get_field_cache(obj, fieldname): +# "Called by _get wrapper" +# hid = hashid(obj, "-%s" % fieldname) +# return hid and _FIELD_CACHE.get(hid, None) or None +# +#def set_field_cache(obj, fieldname, value): +# hid = hashi(obj, "-%s" % fieldname) +# if hid: +# _FIELD_CACHE.set(hid, value) +# +#def flush_field_cache(): +# "Clear the field cache" +# _FIELD_CACHE.clear() #------------------------------------------------------------ @@ -136,7 +147,9 @@ def attr_post_init(sender, instance=None, **kwargs): #print "attr_post_init:", instance, instance.db_obj, instance.db_key hid = hashid(_GA(instance, "db_obj"), "-%s" % _GA(instance, "db_key")) if hid: - _ATTR_CACHE.set(hid, sender) + global _ATTR_CACHE + _ATTR_CACHE[hid] = sender + #_ATTR_CACHE.set(hid, sender) # connected to pre_delete signal (connected in respective Attribute model) def attr_pre_delete(sender, instance=None, **kwargs): @@ -145,14 +158,15 @@ def attr_pre_delete(sender, instance=None, **kwargs): hid = hashid(_GA(instance, "db_obj"), "-%s" % _GA(instance, "db_key")) if hid: #print "attr_pre_delete:", _GA(instance, "db_key") - _ATTR_CACHE.delete(hid) + global _ATTR_CACHE + del _ATTR_CACHE[hid] + #_ATTR_CACHE.delete(hid) # access methods def get_attr_cache(obj, attrname): "Called by get_attribute" hid = hashid(obj, "-%s" % attrname) - _ATTR_CACHE.delete(hid) return hid and _ATTR_CACHE.get(hid, None) or None def set_attr_cache(attrobj): @@ -161,7 +175,9 @@ def set_attr_cache(attrobj): def flush_attr_cache(): "Clear attribute cache" - _ATTR_CACHE.clear() + global _ATTR_CACHE + _ATTR_CACHE = {} + #_ATTR_CACHE.clear() #------------------------------------------------------------ # Property cache - this is a generic cache for properties stored on models. diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index 85cdad472d..ada441f89b 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -426,6 +426,8 @@ class TypedObject(SharedMemoryModel): # Lock storage db_lock_storage = models.TextField('locks', blank=True, help_text="locks limit access to an entity. A lock is defined as a 'lock string' on the form 'type:lockfunctions', defining what functionality is locked and how to determine access. Not defining a lock means no access is granted.") + #db_attributes = models.ManyToManyField(Attribute, related_name="%(app_label)s_%(class)s_related") + # Database manager objects = managers.TypedObjectManager() @@ -460,7 +462,8 @@ class TypedObject(SharedMemoryModel): #@property #def __key_get(self): # "Getter. Allows for value = self.key" - # return get_field_cache(self, "key") + # return _GA(self, "db_key") + # #return get_field_cache(self, "key") ##@key.setter #def __key_set(self, value): # "Setter. Allows for self.key = value" @@ -495,7 +498,8 @@ class TypedObject(SharedMemoryModel): def __typeclass_path_set(self, value): "Setter. Allows for self.typeclass_path = value" _SA(self, "db_typeclass_path", value) - _GA(self, "save")(update_fields=["db_typeclass_path"]) + update_fields = ["db_typeclass_path"] if _GA(self, "_get_pk_val")(_GA(self, "_meta")) is not None else None + _GA(self, "save")(update_fields=update_fields) #@typeclass_path.deleter def __typeclass_path_del(self): "Deleter. Allows for del self.typeclass_path" @@ -587,6 +591,9 @@ class TypedObject(SharedMemoryModel): try: return _GA(self, propname) except AttributeError: + if propname.startswith('_'): + # don't relay private/special varname lookups to the typeclass + raise AttributeError("private property %s not found on db model (typeclass not searched)." % propname) # check if the attribute exists on the typeclass instead # (we make sure to not incur a loop by not triggering the # typeclass' __getattribute__, since that one would diff --git a/src/utils/idmapper/base.py b/src/utils/idmapper/base.py index a1b7d1d770..73412f8c70 100755 --- a/src/utils/idmapper/base.py +++ b/src/utils/idmapper/base.py @@ -18,6 +18,8 @@ from src.utils.utils import dbref from manager import SharedMemoryManager +_FIELD_CACHE_GET = None +_FIELD_CACHE_SET = None _GA = object.__getattribute__ _SA = object.__setattr__ _DA = object.__delattr__ @@ -105,10 +107,12 @@ class SharedMemoryModelBase(ModelBase): "Helper method to create property wrappers with unique names (must be in separate call)" def _get(cls, fname): "Wrapper for getting database field" - value = _GA(cls, fname) - if hasattr(value, "typeclass"): - return _GA(value, "typeclass") #print "_get wrapper:", fname, value, type(value) + value = _GA(cls, fieldname) + if isinstance(value, (basestring, int, float, bool)): + return value + elif hasattr(value, "typeclass"): + return _GA(value, "typeclass") return value def _set(cls, fname, value): "Wrapper for setting database field" @@ -126,16 +130,24 @@ class SharedMemoryModelBase(ModelBase): err = "Could not set %s. Tried to treat value '%s' as a dbref, but no matching object with that id was found." err = err % (fname, value) raise ObjectDoesNotExist(err) - print "_set wrapper:", fname, value, type(value) + #print "_set wrapper:", fname, value, type(value), cls._get_pk_val(cls._meta) _SA(cls, fname, value) - _GA(cls, "save")(update_fields=[fname]) # important - this saves one field only + # only use explicit update_fields in save if we actually have a + # primary key assigned already (won't be when first creating object) + update_fields = [fname] if _GA(cls, "_get_pk_val")(_GA(cls, "_meta")) is not None else None + _GA(cls, "save")(update_fields=update_fields) def _del(cls, fname): - "Wrapper for clearing database field" - raise RuntimeError("You cannot delete field %s on %s; set it to None instead." % (fname, cls)) - type(cls).__setattr__(cls, wrappername, property(fget=lambda cls: _get(cls, fieldname), - fset=lambda cls,val: _set(cls, fieldname, val), - fdel=lambda cls: _del(cls, fieldname), - doc="Wraps setting, saving and caching the %s field." % fieldname)) + "Wrapper for clearing database field - sets it to None" + _SA(cls, fname, None) + update_fields = [fname] if _GA(cls, "_get_pk_val")(_GA(cls, "_meta")) is not None else None + _GA(cls, "save")(update_fields=update_fields) + # create class wrappers + fget = lambda cls: _get(cls, fieldname) + fset = lambda cls, val: _set(cls, fieldname, val) + fdel = lambda cls: _del(cls, fieldname) + doc = "Wraps setting, saving and deleting the %s field." % fieldname + type(cls).__setattr__(cls, wrappername, property(fget, fset, fdel, doc)) + # exclude some models that should not auto-create wrapper fields if cls.__name__ in ("ServerConfig", "TypeNick"): return From a1d818f8aa7c9b107fa669d2c5ab0f72fdecf8b5 Mon Sep 17 00:00:00 2001 From: Griatch Date: Mon, 8 Jul 2013 18:13:21 +0200 Subject: [PATCH 15/49] First test with moving Attributes to m2m field. Not working yet. --- src/objects/models.py | 12 +-- src/players/models.py | 9 +- src/scripts/models.py | 11 +- src/server/caches.py | 62 ++++++----- src/typeclasses/managers.py | 23 +++-- src/typeclasses/models.py | 193 ++++++++++++++++++----------------- src/typeclasses/typeclass.py | 2 +- 7 files changed, 169 insertions(+), 143 deletions(-) diff --git a/src/objects/models.py b/src/objects/models.py index 907feb5945..49cb8609ec 100644 --- a/src/objects/models.py +++ b/src/objects/models.py @@ -17,13 +17,13 @@ transparently through the decorating TypeClass. import traceback from django.db import models from django.conf import settings -from django.db.models.signals import post_init, pre_delete +from django.db.models.signals import m2m_changed from src.utils.idmapper.models import SharedMemoryModel from src.typeclasses.models import Attribute, TypedObject, TypeNick, TypeNickHandler from src.server.caches import get_field_cache, set_field_cache, del_field_cache from src.server.caches import get_prop_cache, set_prop_cache, del_prop_cache -from src.server.caches import attr_post_init, attr_pre_delete + from src.typeclasses.typeclass import TypeClass from src.players.models import PlayerNick from src.objects.manager import ObjectManager @@ -36,7 +36,7 @@ from src.utils.utils import make_iter, to_unicode, variable_from_module, inherit from django.utils.translation import ugettext as _ -#__all__ = ("ObjAttribute", "Alias", "ObjectNick", "ObjectDB") +#__all__ = ("Alias", "ObjectNick", "ObjectDB") _ScriptDB = None _AT_SEARCH_RESULT = variable_from_module(*settings.SEARCH_AT_RESULT.rsplit('.', 1)) @@ -66,8 +66,8 @@ class ObjAttribute(Attribute): verbose_name_plural = "Object Attributes" # attach the cache handlers -post_init.connect(attr_post_init, sender=ObjAttribute, dispatch_uid="objattrcache") -pre_delete.connect(attr_pre_delete, sender=ObjAttribute, dispatch_uid="objattrcache") +#post_init.connect(attr_post_init, sender=ObjAttribute, dispatch_uid="objattrcache") +#pre_delete.connect(attr_pre_delete, sender=ObjAttribute, dispatch_uid="objattrcache") #------------------------------------------------------------ # @@ -518,7 +518,7 @@ class ObjectDB(TypedObject): # this is required to properly handle attributes and typeclass loading. _typeclass_paths = settings.OBJECT_TYPECLASS_PATHS - _attribute_class = ObjAttribute + #_attribute_class = ObjAttribute _db_model_name = "objectdb" # used by attributes to safely store objects _default_typeclass_path = settings.BASE_OBJECT_TYPECLASS or "src.objects.objects.Object" diff --git a/src/players/models.py b/src/players/models.py index 37e639af18..54cbac5214 100644 --- a/src/players/models.py +++ b/src/players/models.py @@ -31,7 +31,6 @@ from django.db.models.signals import post_init, pre_delete from src.server.caches import get_field_cache, set_field_cache, del_field_cache from src.server.caches import get_prop_cache, set_prop_cache, del_prop_cache -from src.server.caches import attr_post_init, attr_pre_delete from src.players import manager from src.scripts.models import ScriptDB @@ -44,7 +43,7 @@ from src.utils.utils import inherits_from, make_iter from django.utils.translation import ugettext as _ -__all__ = ("PlayerAttribute", "PlayerNick", "PlayerDB") +__all__ = ("PlayerNick", "PlayerDB") _ME = _("me") _SELF = _("self") @@ -77,8 +76,8 @@ class PlayerAttribute(Attribute): "Define Django meta options" verbose_name = "Player Attribute" -post_init.connect(attr_post_init, sender=PlayerAttribute, dispatch_uid="playerattrcache") -pre_delete.connect(attr_pre_delete, sender=PlayerAttribute, dispatch_uid="playerattrcache") +#post_init.connect(attr_post_init, sender=PlayerAttribute, dispatch_uid="playerattrcache") +#pre_delete.connect(attr_pre_delete, sender=PlayerAttribute, dispatch_uid="playerattrcache") #------------------------------------------------------------ # @@ -252,7 +251,7 @@ class PlayerDB(TypedObject): # this is required to properly handle attributes and typeclass loading _typeclass_paths = settings.PLAYER_TYPECLASS_PATHS - _attribute_class = PlayerAttribute + #_attribute_class = PlayerAttribute _db_model_name = "playerdb" # used by attributes to safely store objects _default_typeclass_path = settings.BASE_PLAYER_TYPECLASS or "src.players.player.Player" diff --git a/src/scripts/models.py b/src/scripts/models.py index ae79794a9a..e7f1b0efb9 100644 --- a/src/scripts/models.py +++ b/src/scripts/models.py @@ -28,12 +28,11 @@ from django.conf import settings from django.db import models from django.db.models.signals import post_init, pre_delete -from src.server.caches import attr_post_init, attr_pre_delete from src.typeclasses.models import Attribute, TypedObject from django.contrib.contenttypes.models import ContentType from src.scripts.manager import ScriptManager -__all__ = ("ScriptAttribute", "ScriptDB") +__all__ = ("ScriptDB",) #------------------------------------------------------------ # @@ -50,9 +49,9 @@ class ScriptAttribute(Attribute): verbose_name = "Script Attribute" verbose_name_plural = "Script Attributes" -# attach cache handlers for attribute lookup -post_init.connect(attr_post_init, sender=ScriptAttribute, dispatch_uid="scriptattrcache") -pre_delete.connect(attr_pre_delete, sender=ScriptAttribute, dispatch_uid="scriptattrcache") +## attach cache handlers for attribute lookup +#post_init.connect(attr_post_init, sender=ScriptAttribute, dispatch_uid="scriptattrcache") +#pre_delete.connect(attr_pre_delete, sender=ScriptAttribute, dispatch_uid="scriptattrcache") #------------------------------------------------------------ # @@ -254,7 +253,7 @@ class ScriptDB(TypedObject): # this is required to properly handle attributes and typeclass loading _typeclass_paths = settings.SCRIPT_TYPECLASS_PATHS - _attribute_class = ScriptAttribute + #_attribute_class = ScriptAttribute _db_model_name = "scriptdb" # used by attributes to safely store objects _default_typeclass_path = settings.BASE_SCRIPT_TYPECLASS or "src.scripts.scripts.DoNothing" diff --git a/src/server/caches.py b/src/server/caches.py index a3d123b2bd..4bb790d098 100644 --- a/src/server/caches.py +++ b/src/server/caches.py @@ -141,26 +141,34 @@ def field_pre_save(sender, instance=None, update_fields=None, raw=False, **kwarg # to any property). #------------------------------------------------------------ -# connected to post_init signal (connected in respective Attribute model) -def attr_post_init(sender, instance=None, **kwargs): - "Called when attribute is created or retrieved in connection with obj." - #print "attr_post_init:", instance, instance.db_obj, instance.db_key - hid = hashid(_GA(instance, "db_obj"), "-%s" % _GA(instance, "db_key")) - if hid: - global _ATTR_CACHE - _ATTR_CACHE[hid] = sender - #_ATTR_CACHE.set(hid, sender) - -# connected to pre_delete signal (connected in respective Attribute model) -def attr_pre_delete(sender, instance=None, **kwargs): - "Called when attribute is deleted (del_attribute)" - #print "attr_pre_delete:", instance, instance.db_obj, instance.db_key - hid = hashid(_GA(instance, "db_obj"), "-%s" % _GA(instance, "db_key")) - if hid: - #print "attr_pre_delete:", _GA(instance, "db_key") - global _ATTR_CACHE - del _ATTR_CACHE[hid] - #_ATTR_CACHE.delete(hid) +# connected to m2m_changed signal in respective model class +def update_attr_cache(sender, **kwargs): + "Called when the many2many relation changes some way" + obj = kwargs['instance'] + model = kwargs['model'] + action = kwargs['action'] + if kwargs['reverse']: + # the reverse relation changed (the Attribute itself was acted on) + pass + else: + # forward relation changed (the Object holding the Attribute m2m field) + if action == "post_add": + # cache all added objects + for attr_id in kwargs["pk_set"]: + attr_obj = model.objects.get(pk=attr_id) + set_attr_cache(obj, _GA(attr_obj, "db_key"), attr_obj) + elif action == "post_remove": + # obj.db_attributes.remove(attr) was called + for attr_id in kwargs["pk_set"]: + attr_obj = model.objects.get(pk=attr_id) + del_attr_cache(obj, _GA(attr_obj, "db_key")) + attr_obj.delete() + elif action == "post_clear": + # obj.db_attributes.clear() was called + for attr_id in kwargs["pk_set"]: + attr_obj = model.objects.get(pk=attr_id) + del_attr_cache(obj, _GA(attr_obj, "db_key")) + attr_obj.delete() # access methods @@ -169,15 +177,23 @@ def get_attr_cache(obj, attrname): hid = hashid(obj, "-%s" % attrname) return hid and _ATTR_CACHE.get(hid, None) or None -def set_attr_cache(attrobj): +def set_attr_cache(obj, attrname, attrobj): "Set the attr cache manually; this can be used to update" - attr_post_init(None, instance=attrobj) + global _ATTR_CACHE + hid = hashid(obj, "-%s" % attrname) + _ATTR_CACHE[hid] = attrobj + +def del_attr_cache(obj, attrname): + "Del attribute cache" + global _ATTR_CACHE + hid = hashid(obj, "-%s" % attrname) + if hid in _ATTR_CACHE: + del _ATTR_CACHE[hid] def flush_attr_cache(): "Clear attribute cache" global _ATTR_CACHE _ATTR_CACHE = {} - #_ATTR_CACHE.clear() #------------------------------------------------------------ # Property cache - this is a generic cache for properties stored on models. diff --git a/src/typeclasses/managers.py b/src/typeclasses/managers.py index e3630efe47..28ddbe61cb 100644 --- a/src/typeclasses/managers.py +++ b/src/typeclasses/managers.py @@ -5,11 +5,13 @@ all Attributes and TypedObjects). """ from functools import update_wrapper from django.db import models +from django.contrib.contenttypes.models import ContentType from src.utils import idmapper from src.utils.utils import make_iter from src.utils.dbserialize import to_pickle __all__ = ("AttributeManager", "TypedObjectManager") +_GA = object.__getattribute__ # Managers @@ -50,26 +52,33 @@ class AttributeManager(models.Manager): def attr_namesearch(self, searchstr, obj, exact_match=True): """ - Searches the object's attributes for name matches. + Searches the object's attributes for attribute key matches. searchstr: (str) A string to search for. """ # Retrieve the list of attributes for this object. + if exact_match: - return self.filter(db_obj=obj).filter( - db_key__iexact=searchstr) + return _GA("obj", "db_attributes").filter(db_key__iexact=searchstr) else: - return self.filter(db_obj=obj).filter( - db_key__icontains=searchstr) + return _GA("obj", "db_attributes").filter(db_key__icontains=searchstr) def attr_valuesearch(self, searchstr, obj=None): """ - Searches for Attributes with a given value on obj + Searches obj for Attributes with a given value. + searchstr - value to search for. This may be any suitable object. + obj - limit to a given object instance + + If no restraint is given, all Attributes on all types of objects + will be searched. It's highly recommended to at least + supply the objclass argument (DBObject, DBScript or DBPlayer) + to restrict this lookup. """ if obj: - return self.filter(db_obj=obj, db_value=searchstr) + return _GA(obj, "db_attributes").filter(db_value=searchstr) return self.filter(db_value=searchstr) + # # helper functions for the TypedObjectManager. # diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index ada441f89b..94c76420ff 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -34,15 +34,18 @@ import sys import traceback #from collections import defaultdict -from django.db import models, IntegrityError +from django.db import models from django.conf import settings from django.utils.encoding import smart_str from django.contrib.contenttypes.models import ContentType -from django.db.models.fields import AutoField, FieldDoesNotExist from src.utils.idmapper.models import SharedMemoryModel from src.server.caches import get_field_cache, set_field_cache, del_field_cache from src.server.caches import get_attr_cache, set_attr_cache from src.server.caches import get_prop_cache, set_prop_cache, del_prop_cache, flush_attr_cache + +from django.db.models.signals import m2m_changed +from src.server.caches import update_attr_cache + #from src.server.caches import call_ndb_hooks from src.server.models import ServerConfig from src.typeclasses import managers @@ -61,6 +64,7 @@ _GA = object.__getattribute__ _SA = object.__setattr__ _DA = object.__delattr__ + #------------------------------------------------------------ # # Attributes @@ -106,12 +110,12 @@ class Attribute(SharedMemoryModel): db_key = models.CharField('key', max_length=255, db_index=True) # access through the value property - db_value = PickledObjectField('value2', null=True) + db_value = PickledObjectField('value', null=True) # Lock storage db_lock_storage = models.TextField('locks', blank=True) # references the object the attribute is linked to (this is set # by each child class to this abstract class) - db_obj = None # models.ForeignKey("RefencedObject") + db_obj = None # models.ForeignKey("RefencedObject") #TODO-remove # time stamp db_date_created = models.DateTimeField('date_created', editable=False, auto_now_add=True) @@ -128,7 +132,7 @@ class Attribute(SharedMemoryModel): class Meta: "Define Django meta options" - abstract = True + #abstract = True verbose_name = "Evennia Attribute" # Wrapper properties to easily set database fields. These are @@ -426,7 +430,8 @@ class TypedObject(SharedMemoryModel): # Lock storage db_lock_storage = models.TextField('locks', blank=True, help_text="locks limit access to an entity. A lock is defined as a 'lock string' on the form 'type:lockfunctions', defining what functionality is locked and how to determine access. Not defining a lock means no access is granted.") - #db_attributes = models.ManyToManyField(Attribute, related_name="%(app_label)s_%(class)s_related") + # attribute store + db_attributes = models.ManyToManyField(Attribute, null=True, help_text='attributes on this object. An attribute can hold any pickle-able python object (see docs for special cases).') # Database manager objects = managers.TypedObjectManager() @@ -923,10 +928,10 @@ class TypedObject(SharedMemoryModel): # # - # Fully persistent attributes. You usually access these + # Fully attr_obj attributes. You usually access these # through the obj.db.attrname method. - # Helper methods for persistent attributes + # Helper methods for attr_obj attributes def has_attribute(self, attribute_name): """ @@ -935,10 +940,9 @@ class TypedObject(SharedMemoryModel): attribute_name: (str) The attribute's name. """ if not get_attr_cache(self, attribute_name): - attrib_obj = _GA(self, "_attribute_class").objects.filter( - db_obj=self, db_key__iexact=attribute_name) - if attrib_obj: - set_attr_cache(attrib_obj[0]) + attr_obj = _GA(self, "db_attributes").filter(db_key__iexact=attribute_name) + if attr_obj: + set_attr_cache(self, attribute_name, attr_obj[0]) else: return False return True @@ -956,46 +960,38 @@ class TypedObject(SharedMemoryModel): below to perform access-checked modification of attributes. Lock types checked by secureattr are 'attrread','attredit','attrcreate'. """ - attrib_obj = get_attr_cache(self, attribute_name) - if not attrib_obj: - attrclass = _GA(self, "_attribute_class") - # check if attribute already exists. - attrib_obj = attrclass.objects.filter( - db_obj=self, db_key__iexact=attribute_name) - if attrib_obj: - # use old attribute - attrib_obj = attrib_obj[0] - set_attr_cache(attrib_obj) # renew cache + attr_obj = get_attr_cache(self, attribute_name) + if not attr_obj: + # check if attribute already exists + attr_obj = _GA(self, "db_attributes").filter(db_key__iexact=attribute_name) + if attr_obj: + # re-use old attribute object + attr_obj = attr_obj[0] + set_attr_cache(self, attribute_name, attr_obj) # renew cache else: - # no match; create new attribute (this will cache automatically) - attrib_obj = attrclass(db_key=attribute_name, db_obj=self) + # no old attr available; create new (caches automatically) + attr_obj = Attribute(db_key=attribute_name) + attr_obj.save() # important + _GA(self, "db_attributes").add(attr_obj) if lockstring: - attrib_obj.locks.add(lockstring) - # re-set an old attribute value - try: - attrib_obj.value = new_value - except IntegrityError: - # this can happen if the cache was stale and the database object is - # missing. If so we need to clean self.hashid from the cache - flush_attr_cache(self) - self.delete() - raise IntegrityError("Attribute could not be saved - object %s was deleted from database." % self.key) + attr_obj.locks.add(lockstring) + # we shouldn't need to fear stale objects, the signalling should catch all cases + attr_obj.value = new_value def get_attribute_obj(self, attribute_name, default=None): """ Get the actual attribute object named attribute_name """ - attrib_obj = get_attr_cache(self, attribute_name) - if not attrib_obj: - attrib_obj = _GA(self, "_attribute_class").objects.filter( - db_obj=self, db_key__iexact=attribute_name) - if not attrib_obj: + attr_obj = get_attr_cache(self, attribute_name) + if not attr_obj: + attr_obj = _GA(self, "db_attributes").filter(db_key__iexact=attribute_name) + if not attr_obj: return default - set_attr_cache(attrib_obj[0]) #query is first evaluated here - return attrib_obj[0] - return attrib_obj + attr_obj = attr_obj[0] # query evaluated here + set_attr_cache(self, attribute_name, attr_obj) + return attr_obj - def get_attribute(self, attribute_name, default=None): + def get_attribute(self, attribute_name, default=None, raise_exception=False): """ Returns the value of an attribute on an object. You may need to type cast the returned value from this function since the attribute @@ -1003,73 +999,76 @@ class TypedObject(SharedMemoryModel): attribute_name: (str) The attribute's name. default: What to return if no attribute is found + raise_exception (bool) - raise an eception if no object exists instead of returning default. """ - attrib_obj = get_attr_cache(self, attribute_name) - if not attrib_obj: - attrib_obj = _GA(self, "_attribute_class").objects.filter( - db_obj=self, db_key__iexact=attribute_name) - if not attrib_obj: + attr_obj = get_attr_cache(self, attribute_name) + if not attr_obj: + attr_obj = _GA(self, "db_atttributes").filter(db_key__iexact=attribute_name) + if not attr_obj: + if raise_exception: + raise AttributeError return default - set_attr_cache(attrib_obj[0]) #query is first evaluated here - return attrib_obj[0].value - return attrib_obj.value + attr_obj = attr_obj[0] # query is evaluated here + set_attr_cache(self, attribute_name, attr_obj) + return attr_obj.value - def get_attribute_raise(self, attribute_name): - """ - Returns value of an attribute. Raises AttributeError - if no match is found. +# def get_attribute_raise(self, attribute_name): +# """ +# Returns value of an attribute. Raises AttributeError +# if no match is found. +# +# attribute_name: (str) The attribute's name. +# """ +# attr_obj = get_attr_cache(self, attribute_name) +# if not attr_obj: +# attr_obj = _GA(self, "attributes").filter(db_key__iexact=attribute_name) +# if not attr_obj: +# raise AttributeError +# attr_obj = attrib_obj[0] # query is evaluated here +# set_attr_cache(self, attribute_name, attr_obj[0]) +# return attr_obj.value - attribute_name: (str) The attribute's name. - """ - attrib_obj = get_attr_cache(self, attribute_name) - if not attrib_obj: - attrib_obj = _GA(self, "_attribute_class").objects.filter( - db_obj=self, db_key__iexact=attribute_name) - if not attrib_obj: - raise AttributeError - set_attr_cache(attrib_obj[0]) #query is first evaluated here - return attrib_obj[0].value - return attrib_obj.value - - def del_attribute(self, attribute_name): + def del_attribute(self, attribute_name, raise_exception=False): """ Removes an attribute entirely. attribute_name: (str) The attribute's name. + raise_exception (bool) - raise exception if attribute to delete + could not be found """ attr_obj = get_attr_cache(self, attribute_name) if attr_obj: attr_obj.delete() # this will clear attr cache automatically else: - try: - _GA(self, "_attribute_class").objects.filter( - db_obj=self, db_key__iexact=attribute_name)[0].delete() - except IndexError: - pass + attr_obj = _GA(self, "db_attributes").filter(db_key__iexact=attribute_name) + if attr_obj: + attr_obj[0].delete() + elif raise_exception: + raise AttributeError - def del_attribute_raise(self, attribute_name): - """ - Removes and attribute. Raises AttributeError if - attribute is not found. - - attribute_name: (str) The attribute's name. - """ - attr_obj = get_attr_cache(self, attribute_name) - if attr_obj: - attr_obj.delete() # this will clear attr cache automatically - else: - try: - _GA(self, "_attribute_class").objects.filter( - db_obj=self, db_key__iexact=attribute_name)[0].delete() - except IndexError: - pass - raise AttributeError +# def del_attribute_raise(self, attribute_name): +# """ +# Removes and attribute. Raises AttributeError if +# attribute is not found. +# +# attribute_name: (str) The attribute's name. +# """ +# attr_obj = get_attr_cache(self, attribute_name) +# if attr_obj: +# attr_obj.delete() # this will clear attr cache automatically +# else: +# try: +# _GA(self, "_attribute_class").objects.filter( +# db_obj=self, db_key__iexact=attribute_name)[0].delete() +# except IndexError: +# pass +# raise AttributeError def get_all_attributes(self): """ Returns all attributes defined on the object. """ - return list(_GA(self,"_attribute_class").objects.filter(db_obj=self)) + return list(_GA(self, "db_attributes").all()) def attr(self, attribute_name=None, value=None, delete=False): """ @@ -1195,12 +1194,12 @@ class TypedObject(SharedMemoryModel): db = property(__db_get, __db_set, __db_del) # - # NON-PERSISTENT storage methods + # NON-attr_obj storage methods # def nattr(self, attribute_name=None, value=None, delete=False): """ - This is the equivalence of self.attr but for non-persistent + This is the equivalence of self.attr but for non-attr_obj stores. Will not raise error but return None. """ if attribute_name == None: @@ -1226,7 +1225,7 @@ class TypedObject(SharedMemoryModel): #@property def __ndb_get(self): """ - A non-persistent store (ndb: NonDataBase). Everything stored + A non-attr_obj 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. @@ -1235,7 +1234,7 @@ class TypedObject(SharedMemoryModel): return self._ndb_holder except AttributeError: class NdbHolder(object): - "Holder for storing non-persistent attributes." + "Holder for storing non-attr_obj attributes." def get_all(self): return [val for val in self.__dict__.keys() if not val.startswith('_')] @@ -1313,3 +1312,7 @@ class TypedObject(SharedMemoryModel): as a new Typeclass instance. """ self.__class__.flush_cached_instance(self) + + +# connect to signal +m2m_changed.connect(update_attr_cache, sender=TypedObject.db_attributes.through) diff --git a/src/typeclasses/typeclass.py b/src/typeclasses/typeclass.py index 13640d1414..8bd1c2854b 100644 --- a/src/typeclasses/typeclass.py +++ b/src/typeclasses/typeclass.py @@ -168,7 +168,7 @@ class TypeClass(object): log_trace("This is probably due to an unsafe reload.") return # ignore delete try: - dbobj.del_attribute_raise(propname) + dbobj.del_attribute(propname, raise_exception=True) except AttributeError: string = "Object: '%s' not found on %s(#%s), nor on its typeclass %s." raise AttributeError(string % (propname, dbobj, From 2a7c45d6e8d9c98f61a2b67ec9beedd767e18cab Mon Sep 17 00:00:00 2001 From: Griatch Date: Tue, 9 Jul 2013 00:09:19 +0200 Subject: [PATCH 16/49] Run Migrations. Migrated to new Attribute schema, converting old attributes. Not fully tested yet. --- .../migrations/0017_rename_default_cmdsets.py | 1 + .../migrations/0021_auto__del_objattribute.py | 129 +++++++++++ src/objects/models.py | 18 +- .../migrations/0008_converting_attributes.py | 3 +- .../migrations/0009_converting_attributes.py | 3 +- .../0020_auto__del_playerattribute.py | 107 +++++++++ src/players/models.py | 24 +- .../0013_auto__del_scriptattribute.py | 132 +++++++++++ src/scripts/models.py | 18 +- src/server/caches.py | 7 +- src/server/migrations/0003_add_tmpattr.py | 48 ++++ src/server/migrations/0004_store_all_attrs.py | 208 ++++++++++++++++++ .../migrations/0005_auto__del_tmpattribute.py | 39 ++++ src/settings_default.py | 1 + src/typeclasses/migrations/0001_initial.py | 38 ++++ .../migrations/0002_resave_attrs.py | 79 +++++++ src/typeclasses/migrations/__init__.py | 0 src/typeclasses/models.py | 25 +-- 18 files changed, 825 insertions(+), 55 deletions(-) create mode 100644 src/objects/migrations/0021_auto__del_objattribute.py create mode 100644 src/players/migrations/0020_auto__del_playerattribute.py create mode 100644 src/scripts/migrations/0013_auto__del_scriptattribute.py create mode 100644 src/server/migrations/0003_add_tmpattr.py create mode 100644 src/server/migrations/0004_store_all_attrs.py create mode 100644 src/server/migrations/0005_auto__del_tmpattribute.py create mode 100644 src/typeclasses/migrations/0001_initial.py create mode 100644 src/typeclasses/migrations/0002_resave_attrs.py create mode 100644 src/typeclasses/migrations/__init__.py diff --git a/src/objects/migrations/0017_rename_default_cmdsets.py b/src/objects/migrations/0017_rename_default_cmdsets.py index 2a3d93d5e4..adf98919b5 100644 --- a/src/objects/migrations/0017_rename_default_cmdsets.py +++ b/src/objects/migrations/0017_rename_default_cmdsets.py @@ -6,6 +6,7 @@ from django.db import models class Migration(DataMigration): + depends_on = (('players', '0014_add_attr__playable_characters'),) def forwards(self, orm): "Write your forwards methods here." # Note: Remember to use orm['appname.ModelName'] rather than "from appname.models..." diff --git a/src/objects/migrations/0021_auto__del_objattribute.py b/src/objects/migrations/0021_auto__del_objattribute.py new file mode 100644 index 0000000000..b6377a22ea --- /dev/null +++ b/src/objects/migrations/0021_auto__del_objattribute.py @@ -0,0 +1,129 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Deleting model 'ObjAttribute' + db.delete_table(u'objects_objattribute') + + # Adding M2M table for field db_attributes on 'ObjectDB' + db.create_table(u'objects_objectdb_db_attributes', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('objectdb', models.ForeignKey(orm[u'objects.objectdb'], null=False)), + ('attribute', models.ForeignKey(orm[u'typeclasses.attribute'], null=False)) + )) + db.create_unique(u'objects_objectdb_db_attributes', ['objectdb_id', 'attribute_id']) + + + def backwards(self, orm): + # Adding model 'ObjAttribute' + db.create_table(u'objects_objattribute', ( + ('db_lock_storage', self.gf('django.db.models.fields.TextField')(blank=True)), + ('db_value2', self.gf('src.utils.picklefield.PickledObjectField')(null=True)), + ('db_date_created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), + ('db_key', self.gf('django.db.models.fields.CharField')(max_length=255, db_index=True)), + ('db_obj', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['objects.ObjectDB'])), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + )) + db.send_create_signal('objects', ['ObjAttribute']) + + # Removing M2M table for field db_attributes on 'ObjectDB' + db.delete_table('objects_objectdb_db_attributes') + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'objects.alias': { + 'Meta': {'object_name': 'Alias'}, + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['objects.ObjectDB']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'objects.objectdb': { + 'Meta': {'object_name': 'ObjectDB'}, + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destinations_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_home': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'homes_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_location': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locations_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']", 'null': 'True', 'blank': 'True'}), + 'db_sessid': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'objects.objectnick': { + 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'ObjectNick'}, + 'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['objects.ObjectDB']"}), + 'db_real': ('django.db.models.fields.TextField', [], {}), + 'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'players.playerdb': { + 'Meta': {'object_name': 'PlayerDB'}, + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'}) + }, + u'typeclasses.attribute': { + 'Meta': {'object_name': 'Attribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['objects'] \ No newline at end of file diff --git a/src/objects/models.py b/src/objects/models.py index 49cb8609ec..ca6cec98a9 100644 --- a/src/objects/models.py +++ b/src/objects/models.py @@ -56,15 +56,15 @@ _HERE = _("here") #------------------------------------------------------------ -class ObjAttribute(Attribute): - "Attributes for ObjectDB objects." - db_obj = models.ForeignKey("ObjectDB") - - class Meta: - "Define Django meta options" - verbose_name = "Object Attribute" - verbose_name_plural = "Object Attributes" - +#class ObjAttribute(Attribute): +# "Attributes for ObjectDB objects." +# db_obj = models.ForeignKey("ObjectDB") +# +# class Meta: +# "Define Django meta options" +# verbose_name = "Object Attribute" +# verbose_name_plural = "Object Attributes" +# # attach the cache handlers #post_init.connect(attr_post_init, sender=ObjAttribute, dispatch_uid="objattrcache") #pre_delete.connect(attr_pre_delete, sender=ObjAttribute, dispatch_uid="objattrcache") diff --git a/src/players/migrations/0008_converting_attributes.py b/src/players/migrations/0008_converting_attributes.py index d7d91294fd..a970b07e26 100644 --- a/src/players/migrations/0008_converting_attributes.py +++ b/src/players/migrations/0008_converting_attributes.py @@ -10,7 +10,6 @@ except ImportError: import pickle from src.utils.utils import to_str, to_unicode #from src.typeclasses.models import PackedDBobject,PackedDict,PackedList -from src.players.models import PlayerAttribute from django.contrib.contenttypes.models import ContentType CTYPEGET = ContentType.objects.get @@ -370,7 +369,7 @@ class Migration(DataMigration): def forwards(self, orm): "Write your forwards methods here." - for attr in orm.PlayerAttribute.objects.all(): + for attr in orm['players.PlayerAttribute'].objects.all(): try: # repack attr into new format, and reimport val = pickle.loads(to_str(attr.db_value)) diff --git a/src/players/migrations/0009_converting_attributes.py b/src/players/migrations/0009_converting_attributes.py index 3d2ddd083d..fbb4c4bd68 100644 --- a/src/players/migrations/0009_converting_attributes.py +++ b/src/players/migrations/0009_converting_attributes.py @@ -10,7 +10,6 @@ except ImportError: import pickle from src.utils.utils import to_str, to_unicode #from src.typeclasses.models import PackedDBobject -from src.players.models import PlayerAttribute from django.contrib.contenttypes.models import ContentType CTYPEGET = ContentType.objects.get @@ -259,7 +258,7 @@ class Migration(DataMigration): def forwards(self, orm): "Write your forwards methods here." - for attr in orm.PlayerAttribute.objects.all(): + for attr in orm['players.PlayerAttribute'].objects.all(): try: # repack attr into new format, and reimport val = pickle.loads(to_str(attr.db_value)) diff --git a/src/players/migrations/0020_auto__del_playerattribute.py b/src/players/migrations/0020_auto__del_playerattribute.py new file mode 100644 index 0000000000..d58c9324df --- /dev/null +++ b/src/players/migrations/0020_auto__del_playerattribute.py @@ -0,0 +1,107 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Deleting model 'PlayerAttribute' + db.delete_table(u'players_playerattribute') + + # Adding M2M table for field db_attributes on 'PlayerDB' + db.create_table(u'players_playerdb_db_attributes', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('playerdb', models.ForeignKey(orm[u'players.playerdb'], null=False)), + ('attribute', models.ForeignKey(orm[u'typeclasses.attribute'], null=False)) + )) + db.create_unique(u'players_playerdb_db_attributes', ['playerdb_id', 'attribute_id']) + + + def backwards(self, orm): + # Adding model 'PlayerAttribute' + db.create_table(u'players_playerattribute', ( + ('db_lock_storage', self.gf('django.db.models.fields.TextField')(blank=True)), + ('db_value2', self.gf('src.utils.picklefield.PickledObjectField')(null=True)), + ('db_date_created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), + ('db_key', self.gf('django.db.models.fields.CharField')(max_length=255, db_index=True)), + ('db_obj', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['players.PlayerDB'])), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + )) + db.send_create_signal('players', ['PlayerAttribute']) + + # Removing M2M table for field db_attributes on 'PlayerDB' + db.delete_table('players_playerdb_db_attributes') + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'players.playerdb': { + 'Meta': {'object_name': 'PlayerDB'}, + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'}) + }, + u'players.playernick': { + 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, + 'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}), + 'db_real': ('django.db.models.fields.TextField', [], {}), + 'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.attribute': { + 'Meta': {'object_name': 'Attribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['players'] \ No newline at end of file diff --git a/src/players/models.py b/src/players/models.py index 54cbac5214..aa86123d82 100644 --- a/src/players/models.py +++ b/src/players/models.py @@ -64,18 +64,18 @@ _TYPECLASS = None # #------------------------------------------------------------ -class PlayerAttribute(Attribute): - """ - PlayerAttributes work the same way as Attributes on game objects, - but are intended to store OOC information specific to each user - and game (example would be configurations etc). - """ - db_obj = models.ForeignKey("PlayerDB") - - class Meta: - "Define Django meta options" - verbose_name = "Player Attribute" - +#class PlayerAttribute(Attribute): +# """ +# PlayerAttributes work the same way as Attributes on game objects, +# but are intended to store OOC information specific to each user +# and game (example would be configurations etc). +# """ +# db_obj = models.ForeignKey("PlayerDB") +# +# class Meta: +# "Define Django meta options" +# verbose_name = "Player Attribute" +# #post_init.connect(attr_post_init, sender=PlayerAttribute, dispatch_uid="playerattrcache") #pre_delete.connect(attr_pre_delete, sender=PlayerAttribute, dispatch_uid="playerattrcache") diff --git a/src/scripts/migrations/0013_auto__del_scriptattribute.py b/src/scripts/migrations/0013_auto__del_scriptattribute.py new file mode 100644 index 0000000000..2b74eddb9d --- /dev/null +++ b/src/scripts/migrations/0013_auto__del_scriptattribute.py @@ -0,0 +1,132 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Deleting model 'ScriptAttribute' + db.delete_table(u'scripts_scriptattribute') + + # Adding M2M table for field db_attributes on 'ScriptDB' + db.create_table(u'scripts_scriptdb_db_attributes', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('scriptdb', models.ForeignKey(orm[u'scripts.scriptdb'], null=False)), + ('attribute', models.ForeignKey(orm[u'typeclasses.attribute'], null=False)) + )) + db.create_unique(u'scripts_scriptdb_db_attributes', ['scriptdb_id', 'attribute_id']) + + + def backwards(self, orm): + # Adding model 'ScriptAttribute' + db.create_table(u'scripts_scriptattribute', ( + ('db_lock_storage', self.gf('django.db.models.fields.TextField')(blank=True)), + ('db_value2', self.gf('src.utils.picklefield.PickledObjectField')(null=True)), + ('db_date_created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), + ('db_key', self.gf('django.db.models.fields.CharField')(max_length=255, db_index=True)), + ('db_obj', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['scripts.ScriptDB'])), + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + )) + db.send_create_signal('scripts', ['ScriptAttribute']) + + # Removing M2M table for field db_attributes on 'ScriptDB' + db.delete_table('scripts_scriptdb_db_attributes') + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'objects.objectdb': { + 'Meta': {'object_name': 'ObjectDB'}, + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destinations_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_home': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'homes_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_location': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locations_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']", 'null': 'True', 'blank': 'True'}), + 'db_sessid': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'players.playerdb': { + 'Meta': {'object_name': 'PlayerDB'}, + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'}) + }, + u'scripts.scriptdb': { + 'Meta': {'object_name': 'ScriptDB'}, + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_desc': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_interval': ('django.db.models.fields.IntegerField', [], {'default': '-1'}), + 'db_is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['objects.ObjectDB']", 'null': 'True', 'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_persistent': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_repeats': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'db_start_delay': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.attribute': { + 'Meta': {'object_name': 'Attribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['scripts'] \ No newline at end of file diff --git a/src/scripts/models.py b/src/scripts/models.py index e7f1b0efb9..f6b16e786b 100644 --- a/src/scripts/models.py +++ b/src/scripts/models.py @@ -40,15 +40,15 @@ __all__ = ("ScriptDB",) # #------------------------------------------------------------ -class ScriptAttribute(Attribute): - "Attributes for ScriptDB objects." - db_obj = models.ForeignKey("ScriptDB", verbose_name='script') - - class Meta: - "Define Django meta options" - verbose_name = "Script Attribute" - verbose_name_plural = "Script Attributes" - +#class ScriptAttribute(Attribute): +# "Attributes for ScriptDB objects." +# db_obj = models.ForeignKey("ScriptDB", verbose_name='script') +# +# class Meta: +# "Define Django meta options" +# verbose_name = "Script Attribute" +# verbose_name_plural = "Script Attributes" +# ## attach cache handlers for attribute lookup #post_init.connect(attr_post_init, sender=ScriptAttribute, dispatch_uid="scriptattrcache") #pre_delete.connect(attr_pre_delete, sender=ScriptAttribute, dispatch_uid="scriptattrcache") diff --git a/src/server/caches.py b/src/server/caches.py index 4bb790d098..8d36d1f9f8 100644 --- a/src/server/caches.py +++ b/src/server/caches.py @@ -91,7 +91,7 @@ def field_pre_save(sender, instance=None, update_fields=None, raw=False, **kwarg """ if raw: return - print "field_pre_save:", _GA(instance, "db_key") if hasattr(instance, "db_key") else instance, update_fields + print "field_pre_save:", _GA(instance, "db_key"), update_fields# if hasattr(instance, "db_key") else instance, update_fields if update_fields: # this is a list of strings at this point. We want field objects update_fields = (_GA(_GA(instance, "_meta"), "get_field_by_name")(field)[0] for field in update_fields) @@ -108,7 +108,10 @@ def field_pre_save(sender, instance=None, update_fields=None, raw=False, **kwarg handler = None #hid = hashid(instance, "-%s" % fieldname) if callable(handler): - old_value = _GA(instance, _GA(field, "get_cache_name")())#_FIELD_CACHE.get(hid) if hid else None + try: + old_value = _GA(instance, _GA(field, "get_cache_name")())#_FIELD_CACHE.get(hid) if hid else None + except AttributeError: + old_value=None # the handler may modify the stored value in various ways # don't catch exceptions, the handler must work! new_value = handler(new_value, old_value=old_value) diff --git a/src/server/migrations/0003_add_tmpattr.py b/src/server/migrations/0003_add_tmpattr.py new file mode 100644 index 0000000000..19b8019fd9 --- /dev/null +++ b/src/server/migrations/0003_add_tmpattr.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'TmpAttribute' + db.create_table(u'server_tmpattribute', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('db_key', self.gf('django.db.models.fields.CharField')(max_length=255, db_index=True)), + ('db_value', self.gf('src.utils.picklefield.PickledObjectField')(null=True)), + ('db_lock_storage', self.gf('django.db.models.fields.TextField')(blank=True)), + ('db_obj_id', self.gf('django.db.models.fields.IntegerField')(null=True)), + ('db_obj_type', self.gf('django.db.models.fields.CharField')(max_length=10, null=True)), + ('db_date_created', self.gf('django.db.models.fields.DateTimeField')(editable=True, auto_now_add=False)), + )) + db.send_create_signal('server', ['TmpAttribute']) + + + def backwards(self, orm): + # Deleting model 'TmpAttribute' + db.delete_table(u'server_tmpattribute') + + + models = { + u'server.serverconfig': { + 'Meta': {'object_name': 'ServerConfig'}, + 'db_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}), + 'db_value': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'server.tmpattribute': { + 'Meta': {'object_name': 'TmpAttribute'}, + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_obj_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'db_obj_type': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True'}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'db_date_created':('django.db.models.fields.DateTimeField',[],{'editable':'True', 'auto_now_add':'True'}), + } + } + + complete_apps = ['server'] diff --git a/src/server/migrations/0004_store_all_attrs.py b/src/server/migrations/0004_store_all_attrs.py new file mode 100644 index 0000000000..39e2343e4c --- /dev/null +++ b/src/server/migrations/0004_store_all_attrs.py @@ -0,0 +1,208 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import DataMigration +from django.db import models +#from src.utils.dbserialize import to_pickle, from_pickle + +class Migration(DataMigration): + "Store all attributes in a temporary table" + depends_on = (('objects', '0020_remove_old_attr_value_field'), + ('players','0019_remove_old_attr_value_field'), + ('scripts','0012_remove_old_attr_value_field')) + no_dry_run = True + def forwards(self, orm): + "Write your forwards methods here." + # Note: Remember to use orm['appname.ModelName'] rather than "from appname.models..." + + # store ObjectAttributes + for attrobj in orm['objects.ObjAttribute'].objects.all(): + #value = from_pickle(attrobj.db_value, db_obj=attrobj) + new_attr = orm['server.TmpAttribute'](db_key=attrobj.db_key, + db_value=attrobj.db_value, + db_lock_storage=attrobj.db_lock_storage, + db_obj_id=attrobj.db_obj.id, + db_obj_type="objectdb", + db_date_created=attrobj.db_date_created) + new_attr.save() + #new_attr.db_value = to_pickle(value) + #new_attr.save() + + # store PlayerAttributes + for attrobj in orm['players.PlayerAttribute'].objects.all(): + #value = from_pickle(attrobj.db_value, db_obj=attrobj) + new_attr = orm['server.TmpAttribute'](db_key=attrobj.db_key, + db_value=attrobj.db_value, + db_lock_storage=attrobj.db_lock_storage, + db_obj_id=attrobj.db_obj.id, + db_obj_type="playerdb", + db_date_created=attrobj.db_date_created) + new_attr.save() + #new_attr.db_value = to_pickle(value) + #new_attr.save() + + # store ScriptAttributes + for attrobj in orm['scripts.ScriptAttribute'].objects.all(): + #value = from_pickle(attrobj.db_value, db_obj=attrobj) + new_attr = orm['server.TmpAttribute'](db_key=attrobj.db_key, + db_value=attrobj.db_value, + db_lock_storage=attrobj.db_lock_storage, + db_obj_id=attrobj.db_obj.id, + db_obj_type="scriptdb", + db_date_created=attrobj.db_date_created) + new_attr.save() + #new_attr.db_value = to_pickle(value) + #new_attr.save() + + def backwards(self, orm): + "Write your backwards methods here." + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'objects.alias': { + 'Meta': {'object_name': 'Alias'}, + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['objects.ObjectDB']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'objects.objattribute': { + 'Meta': {'object_name': 'ObjAttribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['objects.ObjectDB']"}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'objects.objectdb': { + 'Meta': {'object_name': 'ObjectDB'}, + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destinations_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_home': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'homes_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_location': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locations_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']", 'null': 'True', 'blank': 'True'}), + 'db_sessid': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'objects.objectnick': { + 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'ObjectNick'}, + 'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['objects.ObjectDB']"}), + 'db_real': ('django.db.models.fields.TextField', [], {}), + 'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'players.playerattribute': { + 'Meta': {'object_name': 'PlayerAttribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'players.playerdb': { + 'Meta': {'object_name': 'PlayerDB'}, + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'}) + }, + u'players.playernick': { + 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, + 'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}), + 'db_real': ('django.db.models.fields.TextField', [], {}), + 'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'scripts.scriptattribute': { + 'Meta': {'object_name': 'ScriptAttribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['scripts.ScriptDB']"}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'scripts.scriptdb': { + 'Meta': {'object_name': 'ScriptDB'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_desc': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_interval': ('django.db.models.fields.IntegerField', [], {'default': '-1'}), + 'db_is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['objects.ObjectDB']", 'null': 'True', 'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_persistent': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_repeats': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'db_start_delay': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'server.serverconfig': { + 'Meta': {'object_name': 'ServerConfig'}, + 'db_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}), + 'db_value': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'server.tmpattribute': { + 'Meta': {'object_name': 'TmpAttribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'editable':'True','auto_now_add': 'False', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_obj_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'db_obj_type': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True'}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['objects', 'players', 'scripts', 'server'] + symmetrical = True diff --git a/src/server/migrations/0005_auto__del_tmpattribute.py b/src/server/migrations/0005_auto__del_tmpattribute.py new file mode 100644 index 0000000000..7eab5ae376 --- /dev/null +++ b/src/server/migrations/0005_auto__del_tmpattribute.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + depends_on = (('typeclasses', '0002_resave_attrs'),) + + def forwards(self, orm): + # Deleting model 'TmpAttribute' + db.delete_table(u'server_tmpattribute') + + + def backwards(self, orm): + # Adding model 'TmpAttribute' + db.create_table(u'server_tmpattribute', ( + ('db_key', self.gf('django.db.models.fields.CharField')(max_length=255, db_index=True)), + ('db_obj_id', self.gf('django.db.models.fields.IntegerField')(null=True)), + ('db_obj_type', self.gf('django.db.models.fields.CharField')(max_length=10, null=True)), + ('db_value', self.gf('src.utils.picklefield.PickledObjectField')(null=True)), + ('db_date_created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=False, editable=True, blank=True)), + ('db_lock_storage', self.gf('django.db.models.fields.TextField')(blank=True)), + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + )) + db.send_create_signal('server', ['TmpAttribute']) + + + models = { + u'server.serverconfig': { + 'Meta': {'object_name': 'ServerConfig'}, + 'db_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}), + 'db_value': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['server'] diff --git a/src/settings_default.py b/src/settings_default.py index 0187cc4c62..e055f5c66e 100644 --- a/src/settings_default.py +++ b/src/settings_default.py @@ -497,6 +497,7 @@ INSTALLED_APPS = ( 'django.contrib.admindocs', 'django.contrib.flatpages', 'src.server', + 'src.typeclasses', 'src.players', 'src.objects', 'src.comms', diff --git a/src/typeclasses/migrations/0001_initial.py b/src/typeclasses/migrations/0001_initial.py new file mode 100644 index 0000000000..bc6777daab --- /dev/null +++ b/src/typeclasses/migrations/0001_initial.py @@ -0,0 +1,38 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'Attribute' + db.create_table(u'typeclasses_attribute', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('db_key', self.gf('django.db.models.fields.CharField')(max_length=255, db_index=True)), + ('db_value', self.gf('src.utils.picklefield.PickledObjectField')(null=True)), + ('db_lock_storage', self.gf('django.db.models.fields.TextField')(blank=True)), + ('db_date_created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), + )) + db.send_create_signal(u'typeclasses', ['Attribute']) + + + def backwards(self, orm): + # Deleting model 'Attribute' + db.delete_table(u'typeclasses_attribute') + + + models = { + u'typeclasses.attribute': { + 'Meta': {'object_name': 'Attribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['typeclasses'] \ No newline at end of file diff --git a/src/typeclasses/migrations/0002_resave_attrs.py b/src/typeclasses/migrations/0002_resave_attrs.py new file mode 100644 index 0000000000..b869f51bab --- /dev/null +++ b/src/typeclasses/migrations/0002_resave_attrs.py @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import DataMigration +from django.db import models + +class Migration(DataMigration): + depends_on = (('server', '0003_add_tmpattr'),) + no_dry_run=True + def forwards(self, orm): + "Write your forwards methods here." + # Note: Remember to use orm['appname.ModelName'] rather than "from appname.models..." + + for tmpattr in orm['server.TmpAttribute'].objects.all(): + typ = tmpattr.db_obj_type + dbid = tmpattr.db_obj_id + if typ == 'objectdb': + try: + dbobj = orm['objects.ObjectDB'].objects.get(dbid) + except: + print "could not find objid %i" % objid + continue + elif typ == 'playerdb': + try: + dbobj = orm['players.PlayerDB'].objects.get(dbid) + except: + print "could not find objid %i" % objid + continue + elif typ == 'scriptdb': + try: + dbobj = orm['scripts.ScriptDB'].objects.get(dbid) + except: + print "could not find objid %i" % objid + continue + else: + print "Wrong object type to store on: %s" % typ + continue + dbattr = orm['typeclasses.Attribute'].create(db_key=tmpattr.db_key, + db_value=tmpattr.db_value, + db_lock_storage=tmpattr.db_lock_storage, + db_date_created=tmpattr.db_date) + + dbattr.save() + dbobj.db_attributes.add(dbattr) + + + def backwards(self, orm): + "Write your backwards methods here." + raise RuntimeError("Cannot revert this migration.") + + models = { + u'server.serverconfig': { + 'Meta': {'object_name': 'ServerConfig'}, + 'db_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}), + 'db_value': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'server.tmpattribute': { + 'Meta': {'object_name': 'TmpAttribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_obj_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'db_obj_type': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True'}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.attribute': { + 'Meta': {'object_name': 'Attribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['server', 'typeclasses'] + symmetrical = True diff --git a/src/typeclasses/migrations/__init__.py b/src/typeclasses/migrations/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index 94c76420ff..335db20904 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -71,7 +71,6 @@ _DA = object.__delattr__ # #------------------------------------------------------------ - class Attribute(SharedMemoryModel): """ Abstract django model. @@ -88,34 +87,22 @@ class Attribute(SharedMemoryModel): mode - which type of data is stored in attribute lock_storage - perm strings obj - which object the attribute is defined on - date_created - when the attribute was created - value - the data stored in the attribute - what is actually stored in the field is a dict + date_created - when the attribute was created. + value - the data stored in the attribute, in pickled form + using wrappers to be able to store/retrieve models. - {type : nodb|dbobj|dbiter, - data : } - - where type is info for the loader, telling it if holds a single - dbobject (dbobj), have to do a full scan for dbrefs (dbiter) or - if it is a normal Python structure without any dbobjs inside it - and can thus return it without further action (nodb). """ # # Attribute Database Model setup # - # # These database fields are all set using their corresponding properties, # named same as the field, but withtout the db_* prefix. - db_key = models.CharField('key', max_length=255, db_index=True) # access through the value property db_value = PickledObjectField('value', null=True) # Lock storage db_lock_storage = models.TextField('locks', blank=True) - # references the object the attribute is linked to (this is set - # by each child class to this abstract class) - db_obj = None # models.ForeignKey("RefencedObject") #TODO-remove # time stamp db_date_created = models.DateTimeField('date_created', editable=False, auto_now_add=True) @@ -132,9 +119,9 @@ class Attribute(SharedMemoryModel): class Meta: "Define Django meta options" - #abstract = True verbose_name = "Evennia Attribute" + # 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() @@ -1003,7 +990,7 @@ class TypedObject(SharedMemoryModel): """ attr_obj = get_attr_cache(self, attribute_name) if not attr_obj: - attr_obj = _GA(self, "db_atttributes").filter(db_key__iexact=attribute_name) + attr_obj = _GA(self, "db_attributes").filter(db_key__iexact=attribute_name) if not attr_obj: if raise_exception: raise AttributeError @@ -1315,4 +1302,4 @@ class TypedObject(SharedMemoryModel): # connect to signal -m2m_changed.connect(update_attr_cache, sender=TypedObject.db_attributes.through) +#m2m_changed.connect(update_attr_cache, sender=TypedObject.db_attributes.through) From 033344ad2cae8be0611e551e857c7e1b2af93a1e Mon Sep 17 00:00:00 2001 From: Griatch Date: Wed, 10 Jul 2013 11:06:38 +0200 Subject: [PATCH 17/49] Moved get_evennia_pids into src.utils.utils for more general access. --- src/commands/default/unloggedin.py | 1 + src/server/caches.py | 17 +++++++---------- src/settings_default.py | 18 +----------------- src/utils/idmapper/base.py | 24 ++---------------------- src/utils/utils.py | 25 +++++++++++++++++++++++++ 5 files changed, 36 insertions(+), 49 deletions(-) diff --git a/src/commands/default/unloggedin.py b/src/commands/default/unloggedin.py index d9c5145f7c..5485d14132 100644 --- a/src/commands/default/unloggedin.py +++ b/src/commands/default/unloggedin.py @@ -167,6 +167,7 @@ class CmdUnconnectedCreate(MuxCommand): except Exception, e: session.msg("There was an error creating the default Player/Character:\n%s\n If this problem persists, contact an admin." % e) + logger.log_trace() return # This needs to be called so the engine knows this player is logging in for the first time. diff --git a/src/server/caches.py b/src/server/caches.py index 8d36d1f9f8..1fe9eef25d 100644 --- a/src/server/caches.py +++ b/src/server/caches.py @@ -3,31 +3,28 @@ Central caching module. """ +import os, threading from collections import defaultdict from django.dispatch import Signal from django.core.cache import get_cache -#from django.db.models.signals import pre_save, pre_delete, post_init from src.server.models import ServerConfig -from src.utils.utils import uses_database, to_str +from src.utils.utils import uses_database, to_str, get_evennia_pids _GA = object.__getattribute__ _SA = object.__setattr__ _DA = object.__delattr__ +_IS_SUBPROCESS = os.getpid() in get_evennia_pids() +_IS_MAIN_THREAD = threading.currentThread().getName() == "MainThread" + # -# Open handles to the caches +# Set up the cache stores # -#_FIELD_CACHE = get_cache("field_cache") +_FIELD_CACHE = {} _ATTR_CACHE = {} -#_ATTR_CACHE = get_cache("attr_cache") -#_PROP_CACHE = get_cache("prop_cache") _PROP_CACHE = defaultdict(dict) -# make sure caches are empty at startup -#_FIELD_CACHE.clear() -_ATTR_CACHE.clear() -#_PROP_CACHE.clear() #------------------------------------------------------------ # Cache key hash generation diff --git a/src/settings_default.py b/src/settings_default.py index e055f5c66e..86bd81da09 100644 --- a/src/settings_default.py +++ b/src/settings_default.py @@ -160,23 +160,7 @@ DATABASES = { 'HOST':'', 'PORT':'' }} -# This manages the object-level caches. Evennia will agressively cache -# fields, properties and attribute lookup. Evennia uses a fast and -# local in-memory cache by default. If a Memcached server is available -# it can be used instead (see django docs). Cache performance can be -# tweaked by adding options to each cache. Finally, any cache can -# be completely turned off by pointing its backend -# to 'django.core.cache.backends.dummy.DummyCache'. -CACHES = { - 'default': { - 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}, - 'field_cache': { - 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}, - 'prop_cache': { - 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}, - 'attr_cache': { - 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}, - } + ###################################################################### # Evennia pluggable modules ###################################################################### diff --git a/src/utils/idmapper/base.py b/src/utils/idmapper/base.py index 73412f8c70..2b4e6ce460 100755 --- a/src/utils/idmapper/base.py +++ b/src/utils/idmapper/base.py @@ -14,7 +14,7 @@ from twisted.internet.reactor import callFromThread from django.core.exceptions import ObjectDoesNotExist from django.db.models.base import Model, ModelBase from django.db.models.signals import post_save, pre_delete, post_syncdb -from src.utils.utils import dbref +from src.utils.utils import dbref, get_evennia_pids from manager import SharedMemoryManager @@ -28,31 +28,11 @@ _DA = object.__delattr__ # determine if our current pid is different from the server PID (i.e. # if we are in a subprocess or not) from src import PROC_MODIFIED_OBJS -def _get_pids(): - """ - Get the PID (Process ID) by trying to access - an PID file. - """ - from django.conf import settings - server_pidfile = os.path.join(settings.GAME_DIR, 'server.pid') - portal_pidfile = os.path.join(settings.GAME_DIR, 'portal.pid') - server_pid, portal_pid = None, None - if os.path.exists(server_pidfile): - f = open(server_pidfile, 'r') - server_pid = f.read() - f.close() - if os.path.exists(portal_pidfile): - f = open(portal_pidfile, 'r') - portal_pid = f.read() - f.close() - if server_pid and portal_pid: - return int(server_pid), int(portal_pid) - return None, None # get info about the current process and thread _SELF_PID = os.getpid() -_SERVER_PID, _PORTAL_PID = _get_pids() +_SERVER_PID, _PORTAL_PID = get_evennia_pids() _IS_SUBPROCESS = (_SERVER_PID and _PORTAL_PID) and not _SELF_PID in (_SERVER_PID, _PORTAL_PID) _IS_MAIN_THREAD = threading.currentThread().getName() == "MainThread" diff --git a/src/utils/utils.py b/src/utils/utils.py index 75b52b89ea..c072c36002 100644 --- a/src/utils/utils.py +++ b/src/utils/utils.py @@ -899,3 +899,28 @@ def format_table(table, extra_space=1): for icol, col in enumerate(table)]) return ftable +def get_evennia_pids(): + """ + Get the currently valids PIDs (Process IDs) of the Portal and Server + by trying to access an PID file. This can be used to determine if we + are in a subprocess by something like + + self_pid = os.getpid() + server_pid, portal_pid = get_evennia_pids() + is_subprocess = self_pid not in (server_pid, portal_pid) + + """ + server_pidfile = os.path.join(settings.GAME_DIR, 'server.pid') + portal_pidfile = os.path.join(settings.GAME_DIR, 'portal.pid') + server_pid, portal_pid = None, None + if os.path.exists(server_pidfile): + f = open(server_pidfile, 'r') + server_pid = f.read() + f.close() + if os.path.exists(portal_pidfile): + f = open(portal_pidfile, 'r') + portal_pid = f.read() + f.close() + if server_pid and portal_pid: + return int(server_pid), int(portal_pid) + return None, None From c94472492a2b5fadbc37bc5b9141f6873a369b49 Mon Sep 17 00:00:00 2001 From: Griatch Date: Wed, 10 Jul 2013 19:13:41 +0200 Subject: [PATCH 18/49] Implemented PlayerDB as replacement for User, as per Django1.5. All migrations work, but there are still lots of changes to be done in the code to remove references to the User model. --- src/players/manager.py | 4 +- ...o__add_field_playerdb_db_cmdset_storage.py | 4 +- .../migrations/0020_add_playerdbtmp.py | 162 ++++++++++++++++++ .../0021_copy_user_profile_to_tmp.py | 118 +++++++++++++ .../migrations/0022_delete_old_profile.py | 107 ++++++++++++ .../0023_rename_tmp_player_to_playerdb.py | 101 +++++++++++ src/players/models.py | 74 ++++---- src/server/initial_setup.py | 17 +- src/settings_default.py | 5 +- src/web/news/models.py | 10 +- 10 files changed, 553 insertions(+), 49 deletions(-) create mode 100644 src/players/migrations/0020_add_playerdbtmp.py create mode 100644 src/players/migrations/0021_copy_user_profile_to_tmp.py create mode 100644 src/players/migrations/0022_delete_old_profile.py create mode 100644 src/players/migrations/0023_rename_tmp_player_to_playerdb.py diff --git a/src/players/manager.py b/src/players/manager.py index 9916928f51..b95c96284b 100644 --- a/src/players/manager.py +++ b/src/players/manager.py @@ -4,7 +4,7 @@ The managers for the custom Player object and permissions. import datetime from functools import update_wrapper -from django.contrib.auth.models import User +from django.contrib.auth.models import UserManager from src.typeclasses.managers import returns_typeclass_list, returns_typeclass, TypedObjectManager from src.utils import logger __all__ = ("PlayerManager",) @@ -60,7 +60,7 @@ def returns_player(method): return None return update_wrapper(func, method) -class PlayerManager(TypedObjectManager): +class PlayerManager(TypedObjectManager, UserManager): """ This PlayerManager implements methods for searching and manipulating Players directly from the database. diff --git a/src/players/migrations/0003_auto__add_field_playerdb_db_cmdset_storage.py b/src/players/migrations/0003_auto__add_field_playerdb_db_cmdset_storage.py index c089e1f8ec..3169188d57 100644 --- a/src/players/migrations/0003_auto__add_field_playerdb_db_cmdset_storage.py +++ b/src/players/migrations/0003_auto__add_field_playerdb_db_cmdset_storage.py @@ -7,13 +7,13 @@ from django.db import models class Migration(SchemaMigration): def forwards(self, orm): - + # Adding field 'PlayerDB.db_cmdset_storage' db.add_column('players_playerdb', 'db_cmdset_storage', self.gf('django.db.models.fields.TextField')(null=True), keep_default=False) def backwards(self, orm): - + # Deleting field 'PlayerDB.db_cmdset_storage' db.delete_column('players_playerdb', 'db_cmdset_storage') diff --git a/src/players/migrations/0020_add_playerdbtmp.py b/src/players/migrations/0020_add_playerdbtmp.py new file mode 100644 index 0000000000..8a51877312 --- /dev/null +++ b/src/players/migrations/0020_add_playerdbtmp.py @@ -0,0 +1,162 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models, connection + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'PlayerDBtmp' + if "auth_user" in connection.introspection.table_names(): + # auth_user exists ffrom before. Use that as a base. + db.rename_table('auth_user', 'players_playerdbtmp') + else: + # from-scratch creation; no auth_user table available. Create vanilla User table + db.create_table(u'players_playerdbtmp', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('password', self.gf('django.db.models.fields.CharField')(max_length=128)), + ('last_login', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + ('is_superuser', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('username', self.gf('django.db.models.fields.CharField')(unique=True, max_length=30)), + ('first_name', self.gf('django.db.models.fields.CharField')(max_length=30, blank=True)), + ('last_name', self.gf('django.db.models.fields.CharField')(max_length=30, blank=True)), + ('email', self.gf('django.db.models.fields.EmailField')(max_length=75, blank=True)), + ('is_staff', self.gf('django.db.models.fields.BooleanField')(default=False)), + ('is_active', self.gf('django.db.models.fields.BooleanField')(default=True)), + ('date_joined', self.gf('django.db.models.fields.DateTimeField')(default=datetime.datetime.now)), + )) + db.send_create_signal(u'players', ['PlayerDBtmp']) + + # Adding M2M table for field groups on 'PlayerDBtmp' + db.create_table(u'players_playerdbtmp_groups', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('playerdbtmp', models.ForeignKey(orm[u'players.playerdbtmp'], null=False)), + ('group', models.ForeignKey(orm[u'auth.group'], null=False)) + )) + db.create_unique(u'players_playerdbtmp_groups', ['playerdbtmp_id', 'group_id']) + + # Adding M2M table for field user_permissions on 'PlayerDBtmp' + db.create_table(u'players_playerdbtmp_user_permissions', ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('playerdbtmp', models.ForeignKey(orm[u'players.playerdbtmp'], null=False)), + ('permission', models.ForeignKey(orm[u'auth.permission'], null=False)) + )) + db.create_unique(u'players_playerdbtmp_user_permissions', ['playerdbtmp_id', 'permission_id']) + + # Adding field 'PlayerDB.db_is_connected' + db.add_column(u'players_playerdb', 'db_is_connected', + self.gf('django.db.models.fields.BooleanField')(default=False), + keep_default=False) + + # Adding field 'PlayerDB.db_cmdset_storage' + db.add_column(u'players_playerdb', 'db_cmdset_storage', + self.gf('django.db.models.fields.CharField')(max_length=255, null=True), + keep_default=False) + + # add Evennia-specific columns + db.add_column('players_playerdbtmp', 'db_key', self.gf('django.db.models.fields.CharField')(max_length=255, db_index=True, null=True)) + db.add_column('players_playerdbtmp', 'db_typeclass_path', self.gf('django.db.models.fields.CharField')(max_length=255, null=True)) + db.add_column('players_playerdbtmp', 'db_date_created', self.gf('django.db.models.fields.DateTimeField')(null=True, auto_now_add=True, blank=True)) + db.add_column('players_playerdbtmp', 'db_permissions', self.gf('django.db.models.fields.CharField')(max_length=255, blank=True, null=True)) + db.add_column('players_playerdbtmp', 'db_lock_storage', self.gf('django.db.models.fields.TextField')(blank=True, null=True)) + db.add_column('players_playerdbtmp', 'db_is_connected', self.gf('django.db.models.fields.BooleanField')(default=False)) + db.add_column('players_playerdbtmp', 'db_cmdset_storage', self.gf('django.db.models.fields.CharField')(max_length=255, null=True)) + + def backwards(self, orm): + raise RuntimeError("Cannot revert migration") + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'players.playerattribute': { + 'Meta': {'object_name': 'PlayerAttribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'players.playerdb': { + 'Meta': {'object_name': 'PlayerDB'}, + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'}) + }, + u'players.playerdbtmp': { + 'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDBtmp'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'players.playernick': { + 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, + 'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}), + 'db_real': ('django.db.models.fields.TextField', [], {}), + 'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['players'] diff --git a/src/players/migrations/0021_copy_user_profile_to_tmp.py b/src/players/migrations/0021_copy_user_profile_to_tmp.py new file mode 100644 index 0000000000..030e6d21e8 --- /dev/null +++ b/src/players/migrations/0021_copy_user_profile_to_tmp.py @@ -0,0 +1,118 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import DataMigration +from django.db import models + +class Migration(DataMigration): + + def forwards(self, orm): + "Write your forwards methods here." + # Note: Remember to use orm['appname.ModelName'] rather than "from appname.models..." + if not db.dry_run: + for profile in orm['players.PlayerDB'].objects.all(): + plyr = orm['players.PlayerDBtmp'].objects.get(id=profile.user_id) + plyr.db_cmdset_storage = profile.db_cmdset_storage + plyr.db_date_created = profile.db_date_created + plyr.db_is_connected = profile.db_is_connected + plyr.db_key = profile.db_key + plyr.db_lock_storage = profile.db_lock_storage + plyr.db_typeclass_path = profile.db_typeclass_path + plyr.db_permissions = profile.db_permissions + plyr.save() + + def backwards(self, orm): + "Write your backwards methods here." + raise RuntimeError("Cannot revert this migration.") + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'players.playerattribute': { + 'Meta': {'object_name': 'PlayerAttribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'players.playerdb': { + 'Meta': {'object_name': 'PlayerDB'}, + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'}) + }, + u'players.playerdbtmp': { + 'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDBtmp'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'players.playernick': { + 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, + 'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}), + 'db_real': ('django.db.models.fields.TextField', [], {}), + 'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['players'] + symmetrical = True diff --git a/src/players/migrations/0022_delete_old_profile.py b/src/players/migrations/0022_delete_old_profile.py new file mode 100644 index 0000000000..dd1f7c2dd8 --- /dev/null +++ b/src/players/migrations/0022_delete_old_profile.py @@ -0,0 +1,107 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + db.delete_table('players_playerdb') + + def backwards(self, orm): + raise RuntimeError("Cannot revert this migration") + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'players.playerattribute': { + 'Meta': {'object_name': 'PlayerAttribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'players.playerdb': { + 'Meta': {'object_name': 'PlayerDB'}, + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'}) + }, + u'players.playerdbtmp': { + 'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDBtmp'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'players.playernick': { + 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, + 'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}), + 'db_real': ('django.db.models.fields.TextField', [], {}), + 'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['players'] diff --git a/src/players/migrations/0023_rename_tmp_player_to_playerdb.py b/src/players/migrations/0023_rename_tmp_player_to_playerdb.py new file mode 100644 index 0000000000..1a942b8be1 --- /dev/null +++ b/src/players/migrations/0023_rename_tmp_player_to_playerdb.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + db.rename_table('players_PlayerDBtmp', 'players_PlayerDB') + db.send_create_signal('players', ['PlayerDB']) + + def backwards(self, orm): + raise RuntimeError("Cannot revert this migration.") + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'players.playerattribute': { + 'Meta': {'object_name': 'PlayerAttribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, +# u'players.playerdbtmp': { +# 'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDBtmp'}, +# 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), +# 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), +# 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), +# 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), +# 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), +# 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), +# 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), +# 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), +# 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), +# 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), +# 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), +# u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), +# 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), +# 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), +# 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), +# 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), +# 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), +# 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), +# 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), +# 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) +# }, + u'players.playerdb': { + 'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDB'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'players.playernick': { + 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, + 'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}), + 'db_real': ('django.db.models.fields.TextField', [], {}), + 'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['players'] diff --git a/src/players/models.py b/src/players/models.py index aaab60f7e1..d3b46654ee 100644 --- a/src/players/models.py +++ b/src/players/models.py @@ -25,7 +25,7 @@ account info and OOC account configuration variables etc. from django.conf import settings from django.db import models -from django.contrib.auth.models import User +from django.contrib.auth.models import AbstractUser, User from django.utils.encoding import smart_str from src.server.caches import get_field_cache, set_field_cache, del_field_cache @@ -110,7 +110,8 @@ class PlayerNickHandler(TypeNickHandler): # #------------------------------------------------------------ -class PlayerDB(TypedObject): + +class PlayerDB(TypedObject, AbstractUser): """ This is a special model using Django's 'profile' functionality and extends the default Django User model. It is defined as such @@ -145,8 +146,8 @@ class PlayerDB(TypedObject): # this is the one-to-one link between the customized Player object and # this profile model. It is required by django. - user = models.ForeignKey(User, unique=True, db_index=True, - help_text="The User object holds django-specific authentication for each Player. A unique User should be created and tied to each Player, the two should never be switched or changed around. The User will be deleted automatically when the Player is.") + #user = models.ForeignKey(User, unique=True, db_index=True, + # help_text="The User object holds django-specific authentication for each Player. A unique User should be created and tied to each Player, the two should never be switched or changed around. The User will be deleted automatically when the Player is.") # store a connected flag here too, not just in sessionhandler. # This makes it easier to track from various out-of-process locations db_is_connected = models.BooleanField(default=False, verbose_name="is_connected", help_text="If player is connected to game or not") @@ -254,17 +255,19 @@ class PlayerDB(TypedObject): #@property def __name_get(self): "Getter. Allows for value = self.name" - name = get_prop_cache(self, "_name") - if not name: - name = _GA(self,"user").username - set_prop_cache(self, "_name", name) - return name + return self.username + #name = get_prop_cache(self, "_name") + #if not name: + # name = _GA(self,"user").username + # set_prop_cache(self, "_name", name) + #return name #@name.setter def __name_set(self, value): "Setter. Allows for player.name = newname" - _GA(self, "user").username = value - _GA(self, "user").save() - set_prop_cache(self, "_name", value) + self.username = value + #_GA(self, "user").username = value + #_GA(self, "user").save() + #set_prop_cache(self, "_name", value) #@name.deleter def __name_del(self): "Deleter. Allows for del self.name" @@ -275,11 +278,12 @@ class PlayerDB(TypedObject): #@property def __uid_get(self): "Getter. Retrieves the user id" - uid = get_prop_cache(self, "_uid") - if not uid: - uid = _GA(self, "user").id - set_prop_cache(self, "_uid", uid) - return uid + return self.id + #uid = get_prop_cache(self, "_uid") + #if not uid: + # uid = _GA(self, "user").id + # set_prop_cache(self, "_uid", uid) + #return uid def __uid_set(self, value): raise Exception("User id cannot be set!") def __uid_del(self): @@ -287,14 +291,15 @@ class PlayerDB(TypedObject): uid = property(__uid_get, __uid_set, __uid_del) #@property - def __is_superuser_get(self): - "Superusers have all permissions." - is_suser = get_prop_cache(self, "_is_superuser") - if is_suser == None: - is_suser = _GA(self, "user").is_superuser - set_prop_cache(self, "_is_superuser", is_suser) - return is_suser - is_superuser = property(__is_superuser_get) + #def __is_superuser_get(self): + # "Superusers have all permissions." + # return self.db_is_superuser + # #is_suser = get_prop_cache(self, "_is_superuser") + # #if is_suser == None: + # # is_suser = _GA(self, "user").is_superuser + # # set_prop_cache(self, "_is_superuser", is_suser) + # #return is_suser + #is_superuser = property(__is_superuser_get) # # PlayerDB class access methods @@ -516,16 +521,12 @@ class PlayerDB(TypedObject): self.unpuppet_object(session.sessid) session.sessionhandler.disconnect(session, reason=_("Player being deleted.")) - try: - if _GA(self, "user"): - _GA(_GA(self, "user"), "delete")() - except AssertionError: - pass - try: - super(PlayerDB, self).delete(*args, **kwargs) - except AssertionError: - # this means deleting the user already cleared out the Player object. - pass + #try: + # if _GA(self, "user"): + # _GA(_GA(self, "user"), "delete")() + #except AssertionError: + # pass + super(PlayerDB, self).delete(*args, **kwargs) def execute_cmd(self, raw_string, sessid=None): """ @@ -573,3 +574,6 @@ class PlayerDB(TypedObject): except: pass return matches + +class PlayerDBtmp(AbstractUser): + pass diff --git a/src/server/initial_setup.py b/src/server/initial_setup.py index dc0326fe78..f93da77d5b 100644 --- a/src/server/initial_setup.py +++ b/src/server/initial_setup.py @@ -7,13 +7,15 @@ Everything starts at handle_setup() """ import django -from django.contrib.auth.models import User from django.core import management from django.conf import settings +from django.core.management import call_command +from django.contrib.auth import get_user_model from src.server.models import ServerConfig from src.help.models import HelpEntry from src.utils import create + from django.utils.translation import ugettext as _ def create_config_values(): @@ -25,9 +27,18 @@ def create_config_values(): def get_god_user(): """ - Returns the initially created 'god' User object. + Creates the god user. """ - return User.objects.get(id=1) + PlayerDB = get_user_model() + try: + god_user = PlayerDB.objects.get(id=1) + except PlayerDB.DoesNotExist: + txt = "\n\nNo superuser exists yet. The superuser is the 'owner' account on the" + txt += "\nEvennia server; a good safety fallback. Create a new superuser using the command" + txt += "\n\n python manage.py createsuperuser" + txt += "\n\nFollow the prompts, then restart the server." + raise Exception(txt) + return god_user def create_objects(): """ diff --git a/src/settings_default.py b/src/settings_default.py index 068709af83..90d0509482 100644 --- a/src/settings_default.py +++ b/src/settings_default.py @@ -484,11 +484,12 @@ INSTALLED_APPS = ( 'src.comms', 'src.help', 'src.scripts', - 'src.web.news', + #'src.web.news', 'src.web.website',) # The user profile extends the User object with more functionality; # This should usually not be changed. -AUTH_PROFILE_MODULE = "players.PlayerDB" +AUTH_USER_MODEL = "players.PlayerDB" +#AUTH_PROFILE_MODULE = "players.PlayerDB" # Use a custom test runner that just tests Evennia-specific apps. TEST_RUNNER = 'src.utils.test_utils.EvenniaTestSuiteRunner' diff --git a/src/web/news/models.py b/src/web/news/models.py index 02819644f6..9ea8f54953 100755 --- a/src/web/news/models.py +++ b/src/web/news/models.py @@ -1,7 +1,7 @@ # # This module implements a simple news entry system -# for the evennia website. One needs to use the -# admin interface to add/edit/delete entries. +# for the evennia website. One needs to use the +# admin interface to add/edit/delete entries. # from django.db import models @@ -13,8 +13,8 @@ class NewsTopic(models.Model): """ name = models.CharField(max_length=75, unique=True) description = models.TextField(blank=True) - icon = models.ImageField(upload_to='newstopic_icons', - default='newstopic_icons/default.png', + icon = models.ImageField(upload_to='newstopic_icons', + default='newstopic_icons/default.png', blank=True, help_text="Image for the news topic.") def __str__(self): @@ -35,7 +35,7 @@ class NewsEntry(models.Model): body = models.TextField() topic = models.ForeignKey(NewsTopic, related_name='newstopic') date_posted = models.DateTimeField(auto_now_add=True) - + def __str__(self): return self.title From 2b332c3b9ab12ceee1e94fdef01c1eb3cb06c77a Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 11 Jul 2013 09:51:52 +0200 Subject: [PATCH 19/49] Attribute cache is working, lots of other updates, but still not a cleanly updatable system. It seems the Attribute-migrations are not coming through properly. Fixed a misnamed table in the comm app. --- ev.py | 3 +- src/commands/default/building.py | 8 +- .../0011_renaming_channles_to_channels.py | 135 ++++++++++++++++++ src/comms/models.py | 2 +- src/locks/lockfuncs.py | 2 +- src/objects/admin.py | 9 +- src/objects/manager.py | 21 +-- src/objects/models.py | 21 --- src/objects/tests.py | 27 ++-- src/players/admin.py | 13 +- src/players/models.py | 20 --- src/scripts/admin.py | 23 +-- src/scripts/models.py | 18 --- src/server/caches.py | 50 ++++--- src/server/server.py | 2 +- src/typeclasses/models.py | 54 ++----- 16 files changed, 229 insertions(+), 179 deletions(-) create mode 100644 src/comms/migrations/0011_renaming_channles_to_channels.py diff --git a/ev.py b/ev.py index ce7f3b85af..6518425155 100644 --- a/ev.py +++ b/ev.py @@ -116,9 +116,10 @@ README = __doc__ # help entries from src.help.models import HelpEntry +from src.typeclasses.models import Attribute # players from src.players.player import Player -from src.players.models import PlayerDB, PlayerAttribute, PlayerNick +from src.players.models import PlayerDB, PlayerNick # commands from src.commands.command import Command diff --git a/src/commands/default/building.py b/src/commands/default/building.py index 82d229d021..8492d41dfb 100644 --- a/src/commands/default/building.py +++ b/src/commands/default/building.py @@ -4,8 +4,7 @@ Building and world design commands """ from django.conf import settings -from src.objects.models import ObjectDB, ObjAttribute -from src.players.models import PlayerAttribute +from src.objects.models import ObjectDB from src.utils import create, utils from src.utils.ansi import raw from src.commands.default.muxcommand import MuxCommand @@ -1545,10 +1544,7 @@ class CmdExamine(ObjManipCommand): except Exception: ndb_attr = None else: - if self.player_mode: - db_attr = [(attr.key, attr.value) for attr in PlayerAttribute.objects.filter(db_obj=obj)] - else: - db_attr = [(attr.key, attr.value) for attr in ObjAttribute.objects.filter(db_obj=obj)] + db_attr = [(attr.key, attr.value) for attr in obj.db_attributes.all()] try: ndb_attr = [(aname, avalue) for aname, avalue in obj.ndb.__dict__.items() if not aname.startswith("_")] except Exception: diff --git a/src/comms/migrations/0011_renaming_channles_to_channels.py b/src/comms/migrations/0011_renaming_channles_to_channels.py new file mode 100644 index 0000000000..b859446955 --- /dev/null +++ b/src/comms/migrations/0011_renaming_channles_to_channels.py @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Renaming M2M table for field db_hide_from_channles on 'Msg' + db.rename_table('comms_msg_db_hide_from_channles', 'comms_msg_db_hide_from_channels') + + def backwards(self, orm): + raise RuntimeException("Cannot revert this migration.") + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'comms.channel': { + 'Meta': {'object_name': 'Channel'}, + 'db_aliases': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + 'db_desc': ('django.db.models.fields.CharField', [], {'max_length': '80', 'null': 'True', 'blank': 'True'}), + 'db_keep_log': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'comms.externalchannelconnection': { + 'Meta': {'object_name': 'ExternalChannelConnection'}, + 'db_channel': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['comms.Channel']"}), + 'db_external_config': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_external_key': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'db_external_send_code': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_is_enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'comms.msg': { + 'Meta': {'object_name': 'Msg'}, + 'db_date_sent': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}), + 'db_header': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'db_hide_from_channels': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'hide_from_channels_set'", 'null': 'True', 'to': u"orm['comms.Channel']"}), + 'db_hide_from_objects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'hide_from_objects_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_hide_from_players': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'hide_from_players_set'", 'null': 'True', 'to': u"orm['players.PlayerDB']"}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_message': ('django.db.models.fields.TextField', [], {}), + 'db_receivers_channels': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'channel_set'", 'null': 'True', 'to': u"orm['comms.Channel']"}), + 'db_receivers_objects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'receiver_object_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_receivers_players': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'receiver_player_set'", 'null': 'True', 'to': u"orm['players.PlayerDB']"}), + 'db_sender_external': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'db_index': 'True'}), + 'db_sender_objects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'sender_object_set'", 'null': 'True', 'db_index': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_sender_players': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'sender_player_set'", 'null': 'True', 'db_index': 'True', 'to': u"orm['players.PlayerDB']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'comms.playerchannelconnection': { + 'Meta': {'object_name': 'PlayerChannelConnection'}, + 'db_channel': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['comms.Channel']"}), + 'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'objects.objectdb': { + 'Meta': {'object_name': 'ObjectDB'}, + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destinations_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_home': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'homes_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_location': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locations_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']", 'null': 'True', 'blank': 'True'}), + 'db_sessid': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'players.playerdb': { + 'Meta': {'object_name': 'PlayerDB'}, + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'}) + }, + u'typeclasses.attribute': { + 'Meta': {'object_name': 'Attribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['comms'] diff --git a/src/comms/models.py b/src/comms/models.py index 3c62c34815..187ddf4b99 100644 --- a/src/comms/models.py +++ b/src/comms/models.py @@ -88,7 +88,7 @@ class Msg(SharedMemoryModel): # these can be used to filter/hide a given message from supplied objects/players/channels db_hide_from_players = models.ManyToManyField("players.PlayerDB", related_name='hide_from_players_set', null=True) db_hide_from_objects = models.ManyToManyField("objects.ObjectDB", related_name='hide_from_objects_set', null=True) - db_hide_from_channles = models.ManyToManyField("Channel", related_name='hide_from_channels_set', null=True) + db_hide_from_channels = models.ManyToManyField("Channel", related_name='hide_from_channels_set', null=True) # Database manager objects = managers.MsgManager() diff --git a/src/locks/lockfuncs.py b/src/locks/lockfuncs.py index d5c7f6ceb8..162623c838 100644 --- a/src/locks/lockfuncs.py +++ b/src/locks/lockfuncs.py @@ -134,7 +134,7 @@ def perm(accessing_obj, accessed_obj, *args, **kwargs): permission is also granted to all ranks higher up in the hierarchy. If accessing_object is an Object controlled by a Player, the - permissions of the Player is used unless the PlayerAttribute _quell + permissions of the Player is used unless the Attribute _quell is set to True on the Object. In this case however, the LOWEST hieararcy-permission of the Player/Object-pair will be used (this is order to avoid Players potentially escalating their own permissions diff --git a/src/objects/admin.py b/src/objects/admin.py index cf9a66449d..2e7a9448de 100644 --- a/src/objects/admin.py +++ b/src/objects/admin.py @@ -6,12 +6,13 @@ from django import forms from django.conf import settings from django.contrib import admin -from src.objects.models import ObjAttribute, ObjectDB, ObjectNick, Alias +from src.typeclases.models import Attribute +from src.objects.models import ObjectDB, ObjectNick, Alias from src.utils.utils import mod_import -class ObjAttributeInline(admin.TabularInline): - model = ObjAttribute +class AttributeInline(admin.TabularInline): + model = Attribute fields = ('db_key', 'db_value') extra = 0 @@ -80,7 +81,7 @@ class ObjectDBAdmin(admin.ModelAdmin): ) #deactivated temporarily, they cause empty objects to be created in admin - #inlines = [AliasInline, ObjAttributeInline] + #inlines = [AliasInline, AttributeInline] # Custom modification to give two different forms wether adding or not. diff --git a/src/objects/manager.py b/src/objects/manager.py index 41866a3d6b..76aa1692f2 100644 --- a/src/objects/manager.py +++ b/src/objects/manager.py @@ -13,7 +13,7 @@ __all__ = ("ObjectManager",) _GA = object.__getattribute__ # delayed import -_OBJATTR = None +_ATTR = None # Try to use a custom way to parse id-tagged multimatches. @@ -139,15 +139,16 @@ class ObjectManager(TypedObjectManager): #q = self.filter(cand_restriction & type_restriction & Q(objattribute__db_key=attribute_name) & Q(objattribute__db_value=attribute_value)) #return list(q) - if isinstance(attribute_value, (basestring, int, float, bool, long)): - return self.filter(cand_restriction & type_restriction & Q(objattribute__db_key=attribute_name, objattribute__db_value=attribute_value)) - else: - # We have to loop for safety since the referenced lookup gives deepcopy error if attribute value is an object. - global _OBJATTR - if not _OBJATTR: - from src.objects.models import ObjAttribute as _OBJATTR - cands = list(self.filter(cand_restriction & type_restriction & Q(objattribute__db_key=attribute_name))) - return [_GA(attr, "db_obj") for attr in _OBJATTR.objects.filter(db_obj__in=cands, db_value=attribute_value)] + #if isinstance(attribute_value, (basestring, int, float, bool, long)): + return self.filter(cand_restriction & type_restriction & Q(db_attributes__db_key=attribute_name, db_attributes__db_value=attribute_value)) + #else: + # # We have to loop for safety since the referenced lookup gives deepcopy error if attribute value is an object. + # global _ATTR + # if not _ATTR: + # from src.typeclasses.models import Attribute as _ATTR + # cands = list(self.filter(cand_restriction & type_restriction & Q(objattribute__db_key=attribute_name))) + # return [_ATTR. + # return [_GA(attr, "db_obj") for attr in _OBJATTR.objects.filter(db_obj__in=cands, db_value=attribute_value)] @returns_typeclass_list def get_objs_with_db_property(self, property_name, candidates=None): diff --git a/src/objects/models.py b/src/objects/models.py index ca6cec98a9..78f928fe21 100644 --- a/src/objects/models.py +++ b/src/objects/models.py @@ -17,7 +17,6 @@ transparently through the decorating TypeClass. import traceback from django.db import models from django.conf import settings -from django.db.models.signals import m2m_changed from src.utils.idmapper.models import SharedMemoryModel from src.typeclasses.models import Attribute, TypedObject, TypeNick, TypeNickHandler @@ -49,26 +48,6 @@ _ME = _("me") _SELF = _("self") _HERE = _("here") -#------------------------------------------------------------ -# -# ObjAttribute -# -#------------------------------------------------------------ - - -#class ObjAttribute(Attribute): -# "Attributes for ObjectDB objects." -# db_obj = models.ForeignKey("ObjectDB") -# -# class Meta: -# "Define Django meta options" -# verbose_name = "Object Attribute" -# verbose_name_plural = "Object Attributes" -# -# attach the cache handlers -#post_init.connect(attr_post_init, sender=ObjAttribute, dispatch_uid="objattrcache") -#pre_delete.connect(attr_pre_delete, sender=ObjAttribute, dispatch_uid="objattrcache") - #------------------------------------------------------------ # # Alias diff --git a/src/objects/tests.py b/src/objects/tests.py index a9e43cb915..dbf45d209e 100644 --- a/src/objects/tests.py +++ b/src/objects/tests.py @@ -34,19 +34,20 @@ class TestObjAttrs(TestCase): """ Test aspects of ObjAttributes """ - def setUp(self): - "set up the test" - self.attr = models.ObjAttribute() - self.obj1 = create.create_object(objects.Object, key="testobj1", location=None) - self.obj2 = create.create_object(objects.Object, key="testobj2", location=self.obj1) - def test_store_str(self): - hstring = u"sdfv00=97sfjs842 ivfjlQKFos9GF^8dddsöäå-?%" - self.obj1.db.testattr = hstring - self.assertEqual(hstring, self.obj1.db.testattr) - def test_store_obj(self): - self.obj1.db.testattr = self.obj2 - self.assertEqual(self.obj2 ,self.obj1.db.testattr) - self.assertEqual(self.obj2.location, self.obj1.db.testattr.location) + pass +# def setUp(self): +# "set up the test" +# self.attr = models.ObjAttribute() +# self.obj1 = create.create_object(objects.Object, key="testobj1", location=None) +# self.obj2 = create.create_object(objects.Object, key="testobj2", location=self.obj1) +# def test_store_str(self): +# hstring = u"sdfv00=97sfjs842 ivfjlQKFos9GF^8dddsöäå-?%" +# self.obj1.db.testattr = hstring +# self.assertEqual(hstring, self.obj1.db.testattr) +# def test_store_obj(self): +# self.obj1.db.testattr = self.obj2 +# self.assertEqual(self.obj2 ,self.obj1.db.testattr) +# self.assertEqual(self.obj2.location, self.obj1.db.testattr.location) def suite(): """ diff --git a/src/players/admin.py b/src/players/admin.py index 64e8e3d36b..6c0142fe4f 100644 --- a/src/players/admin.py +++ b/src/players/admin.py @@ -11,7 +11,8 @@ from django.contrib.auth.admin import UserAdmin as BaseUserAdmin from django.contrib.admin import widgets from django.contrib.auth.forms import UserChangeForm, UserCreationForm from django.contrib.auth.models import User -from src.players.models import PlayerDB, PlayerAttribute +from src.players.models import PlayerDB +from src.typeclasses.models import Attribute from src.utils import logger, create # remove User itself from admin site @@ -49,20 +50,20 @@ class CustomUserCreationForm(UserCreationForm): # # The Player editor -# class PlayerAttributeForm(forms.ModelForm): +# class AttributeForm(forms.ModelForm): # "Defines how to display the atttributes" # class Meta: -# model = PlayerAttribute +# model = Attribute # db_key = forms.CharField(label="Key", # widget=forms.TextInput(attrs={'size':'15'})) # db_value = forms.CharField(label="Value", # widget=forms.Textarea(attrs={'rows':'2'})) -# class PlayerAttributeInline(admin.TabularInline): +# class AttributeInline(admin.TabularInline): # "Inline creation of player attributes" -# model = PlayerAttribute +# model = Attribute # extra = 0 -# form = PlayerAttributeForm +# form = AttributeForm # fieldsets = ( # (None, {'fields' : (('db_key', 'db_value'))}),) diff --git a/src/players/models.py b/src/players/models.py index aa86123d82..be090531c8 100644 --- a/src/players/models.py +++ b/src/players/models.py @@ -58,26 +58,6 @@ _DA = object.__delattr__ _TYPECLASS = None -#------------------------------------------------------------ -# -# PlayerAttribute -# -#------------------------------------------------------------ - -#class PlayerAttribute(Attribute): -# """ -# PlayerAttributes work the same way as Attributes on game objects, -# but are intended to store OOC information specific to each user -# and game (example would be configurations etc). -# """ -# db_obj = models.ForeignKey("PlayerDB") -# -# class Meta: -# "Define Django meta options" -# verbose_name = "Player Attribute" -# -#post_init.connect(attr_post_init, sender=PlayerAttribute, dispatch_uid="playerattrcache") -#pre_delete.connect(attr_pre_delete, sender=PlayerAttribute, dispatch_uid="playerattrcache") #------------------------------------------------------------ # diff --git a/src/scripts/admin.py b/src/scripts/admin.py index b6ba5610b6..da8a492ecd 100644 --- a/src/scripts/admin.py +++ b/src/scripts/admin.py @@ -1,31 +1,32 @@ # -# This sets up how models are displayed -# in the web admin interface. +# This sets up how models are displayed +# in the web admin interface. # -from src.scripts.models import ScriptAttribute, ScriptDB +from src.typeclasses.models import Attribute +from src.scripts.models import ScriptDB from django.contrib import admin -class ScriptAttributeInline(admin.TabularInline): - model = ScriptAttribute - fields = ('db_key', 'db_value') +class AttributeInline(admin.TabularInline): + model = Attribute + fields = ('db_key', 'db_value') max_num = 1 class ScriptDBAdmin(admin.ModelAdmin): list_display = ('id', 'db_key', 'db_typeclass_path', 'db_obj', 'db_interval', 'db_repeats', 'db_persistent') list_display_links = ('id', 'db_key') - ordering = ['db_obj', 'db_typeclass_path'] - search_fields = ['^db_key', 'db_typeclass_path'] - save_as = True + ordering = ['db_obj', 'db_typeclass_path'] + search_fields = ['^db_key', 'db_typeclass_path'] + save_as = True save_on_top = True - list_select_related = True + list_select_related = True fieldsets = ( (None, { 'fields':(('db_key', 'db_typeclass_path'), 'db_interval', 'db_repeats', 'db_start_delay', 'db_persistent', 'db_obj')}), ) - #inlines = [ScriptAttributeInline] + #inlines = [AttributeInline] admin.site.register(ScriptDB, ScriptDBAdmin) diff --git a/src/scripts/models.py b/src/scripts/models.py index f6b16e786b..d275dd5fe1 100644 --- a/src/scripts/models.py +++ b/src/scripts/models.py @@ -34,24 +34,6 @@ from src.scripts.manager import ScriptManager __all__ = ("ScriptDB",) -#------------------------------------------------------------ -# -# ScriptAttribute -# -#------------------------------------------------------------ - -#class ScriptAttribute(Attribute): -# "Attributes for ScriptDB objects." -# db_obj = models.ForeignKey("ScriptDB", verbose_name='script') -# -# class Meta: -# "Define Django meta options" -# verbose_name = "Script Attribute" -# verbose_name_plural = "Script Attributes" -# -## attach cache handlers for attribute lookup -#post_init.connect(attr_post_init, sender=ScriptAttribute, dispatch_uid="scriptattrcache") -#pre_delete.connect(attr_pre_delete, sender=ScriptAttribute, dispatch_uid="scriptattrcache") #------------------------------------------------------------ # diff --git a/src/server/caches.py b/src/server/caches.py index 1fe9eef25d..e93cc5da67 100644 --- a/src/server/caches.py +++ b/src/server/caches.py @@ -5,7 +5,7 @@ Central caching module. import os, threading from collections import defaultdict -from django.dispatch import Signal + from django.core.cache import get_cache from src.server.models import ServerConfig from src.utils.utils import uses_database, to_str, get_evennia_pids @@ -84,16 +84,18 @@ def hashid(obj, suffix=""): def field_pre_save(sender, instance=None, update_fields=None, raw=False, **kwargs): """ Called at the beginning of the save operation. The save method - must be called with the update_fields keyword in order to + must be called with the update_fields keyword in order to be most efficient. + This method should NOT save; rather it is the save() that triggers this function. + Its main purpose is to allow to plug-in a save handler. """ if raw: return - print "field_pre_save:", _GA(instance, "db_key"), update_fields# if hasattr(instance, "db_key") else instance, update_fields + print "field_pre_save:", instance, update_fields# if hasattr(instance, "db_key") else instance, update_fields if update_fields: # this is a list of strings at this point. We want field objects update_fields = (_GA(_GA(instance, "_meta"), "get_field_by_name")(field)[0] for field in update_fields) else: - # meta.fields are already field objects + # meta.fields are already field objects; get them all update_fields = _GA(_GA(instance, "_meta"), "fields") for field in update_fields: fieldname = field.name @@ -116,7 +118,7 @@ def field_pre_save(sender, instance=None, update_fields=None, raw=False, **kwarg _SA(instance, fieldname, new_value) #if hid: # # update cache - # _FIELD_CACHE.set(hid, new_value) + # _FIELD_CACHE[hid] = new_value # access method # @@ -134,6 +136,23 @@ def field_pre_save(sender, instance=None, update_fields=None, raw=False, **kwarg # "Clear the field cache" # _FIELD_CACHE.clear() +def get_cache_sizes(): + return (0, 0), (0, 0), (0, 0) +def get_field_cache(obj, name): + return _GA(obj, "db_%s" % name) +def set_field_cache(obj, name, val): + _SA(obj, "db_%s" % name, val) + _GA(obj, "save")() + #hid = hashid(obj) + #if _OOB_FIELD_UPDATE_HOOKS[hid].get(name): + # _OOB_HANDLER.update(hid, name, val) +def del_field_cache(obj, name): + _SA(obj, "db_%s" % name, None) + _GA(obj, "save")() + #hid = hashid(obj) + #if _OOB_FIELD_UPDATE_HOOKS[hid].get(name): + # _OOB_HANDLER.update(hid, name, None) + #------------------------------------------------------------ # Attr cache - caching the attribute objects related to a given object to @@ -142,11 +161,12 @@ def field_pre_save(sender, instance=None, update_fields=None, raw=False, **kwarg #------------------------------------------------------------ # connected to m2m_changed signal in respective model class -def update_attr_cache(sender, **kwargs): +def post_attr_update(sender, **kwargs): "Called when the many2many relation changes some way" obj = kwargs['instance'] model = kwargs['model'] action = kwargs['action'] + print "update_attr_cache:", obj, model, action if kwargs['reverse']: # the reverse relation changed (the Attribute itself was acted on) pass @@ -499,22 +519,6 @@ def flush_prop_cache(): #else: # local caches disabled. Use simple pass-through replacements -def get_cache_sizes(): - return (0, 0), (0, 0), (0, 0) -def get_field_cache(obj, name): - return _GA(obj, "db_%s" % name) -def set_field_cache(obj, name, val): - _SA(obj, "db_%s" % name, val) - _GA(obj, "save")() - #hid = hashid(obj) - #if _OOB_FIELD_UPDATE_HOOKS[hid].get(name): - # _OOB_HANDLER.update(hid, name, val) -def del_field_cache(obj, name): - _SA(obj, "db_%s" % name, None) - _GA(obj, "save")() - #hid = hashid(obj) - #if _OOB_FIELD_UPDATE_HOOKS[hid].get(name): - # _OOB_HANDLER.update(hid, name, None) #def flush_field_cache(obj=None): # pass # these should get oob handlers when oob is implemented. @@ -531,7 +535,7 @@ def del_field_cache(obj, name): #def set_attr_cache(obj, attrname, attrobj): # pass #def del_attr_cache(obj, attrname): -# passk +# pass #def flush_attr_cache(obj=None): # pass diff --git a/src/server/server.py b/src/server/server.py index 7cc7e685a9..b7e8f6a281 100644 --- a/src/server/server.py +++ b/src/server/server.py @@ -156,7 +156,7 @@ class Evennia(object): #from src.players.models import PlayerDB for i, prev, curr in ((i, tup[0], tup[1]) for i, tup in enumerate(settings_compare) if i in mismatches): # update the database - print " one or more default cmdset/typeclass settings changed. Updating defaults stored in database ..." + print " %s:\n '%s' changed to '%s'. Updating unchanged entries in database ..." % (settings_names[i], prev, curr) if i == 0: [obj.__setattr__("cmdset_storage", curr) for obj in ObjectDB.objects.filter(db_cmdset_storage__exact=prev)] if i == 1: [ply.__setattr__("cmdset_storage", curr) for ply in PlayerDB.objects.filter(db_cmdset_storage__exact=prev)] if i == 2: [ply.__setattr__("typeclass_path", curr) for ply in PlayerDB.objects.filter(db_typeclass_path__exact=prev)] diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index 335db20904..631506fd82 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -44,7 +44,7 @@ from src.server.caches import get_attr_cache, set_attr_cache from src.server.caches import get_prop_cache, set_prop_cache, del_prop_cache, flush_attr_cache from django.db.models.signals import m2m_changed -from src.server.caches import update_attr_cache +from src.server.caches import post_attr_update #from src.server.caches import call_ndb_hooks from src.server.models import ServerConfig @@ -999,22 +999,6 @@ class TypedObject(SharedMemoryModel): set_attr_cache(self, attribute_name, attr_obj) return attr_obj.value -# def get_attribute_raise(self, attribute_name): -# """ -# Returns value of an attribute. Raises AttributeError -# if no match is found. -# -# attribute_name: (str) The attribute's name. -# """ -# attr_obj = get_attr_cache(self, attribute_name) -# if not attr_obj: -# attr_obj = _GA(self, "attributes").filter(db_key__iexact=attribute_name) -# if not attr_obj: -# raise AttributeError -# attr_obj = attrib_obj[0] # query is evaluated here -# set_attr_cache(self, attribute_name, attr_obj[0]) -# return attr_obj.value - def del_attribute(self, attribute_name, raise_exception=False): """ Removes an attribute entirely. @@ -1024,32 +1008,16 @@ class TypedObject(SharedMemoryModel): could not be found """ attr_obj = get_attr_cache(self, attribute_name) - if attr_obj: - attr_obj.delete() # this will clear attr cache automatically - else: + if not attr_obj: attr_obj = _GA(self, "db_attributes").filter(db_key__iexact=attribute_name) - if attr_obj: - attr_obj[0].delete() - elif raise_exception: + attr_obj = attr_obj[0] if attr_obj else None + if not attr_obj: + if raise_exception: raise AttributeError - -# def del_attribute_raise(self, attribute_name): -# """ -# Removes and attribute. Raises AttributeError if -# attribute is not found. -# -# attribute_name: (str) The attribute's name. -# """ -# attr_obj = get_attr_cache(self, attribute_name) -# if attr_obj: -# attr_obj.delete() # this will clear attr cache automatically -# else: -# try: -# _GA(self, "_attribute_class").objects.filter( -# db_obj=self, db_key__iexact=attribute_name)[0].delete() -# except IndexError: -# pass -# raise AttributeError + return + # the post-remove cache signal will auto-delete the attribute as well, + # don't call attr_obj.delete() after this. + self.db_attributes.remove(attr_obj) def get_all_attributes(self): """ @@ -1301,5 +1269,5 @@ class TypedObject(SharedMemoryModel): self.__class__.flush_cached_instance(self) -# connect to signal -#m2m_changed.connect(update_attr_cache, sender=TypedObject.db_attributes.through) +# connect to attribut cache signal +m2m_changed.connect(post_attr_update, sender=TypedObject.db_attributes.through) From f1ba0ca177b9400df7c47f3d4fd1cc71b3698e32 Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 11 Jul 2013 14:12:42 +0200 Subject: [PATCH 20/49] Fixed attribute import migrations. --- .../migrations/0002_resave_attrs.py | 131 ++++++++++++++++-- 1 file changed, 119 insertions(+), 12 deletions(-) diff --git a/src/typeclasses/migrations/0002_resave_attrs.py b/src/typeclasses/migrations/0002_resave_attrs.py index b869f51bab..0fa7792857 100644 --- a/src/typeclasses/migrations/0002_resave_attrs.py +++ b/src/typeclasses/migrations/0002_resave_attrs.py @@ -5,7 +5,10 @@ from south.v2 import DataMigration from django.db import models class Migration(DataMigration): - depends_on = (('server', '0003_add_tmpattr'),) + depends_on = (('server', '0004_store_all_attrs'), + ('objects', '0021_auto__del_objattribute'), + ('players', '0020_auto__del_playerattribute'), + ('scripts', '0013_auto__del_scriptattribute')) no_dry_run=True def forwards(self, orm): "Write your forwards methods here." @@ -16,29 +19,29 @@ class Migration(DataMigration): dbid = tmpattr.db_obj_id if typ == 'objectdb': try: - dbobj = orm['objects.ObjectDB'].objects.get(dbid) + dbobj = orm['objects.ObjectDB'].objects.get(id=dbid) except: - print "could not find objid %i" % objid + print "could not find objid %i" % dbid continue elif typ == 'playerdb': try: - dbobj = orm['players.PlayerDB'].objects.get(dbid) + dbobj = orm['players.PlayerDB'].objects.get(id=dbid) except: - print "could not find objid %i" % objid + print "could not find objid %i" % dbid continue elif typ == 'scriptdb': try: - dbobj = orm['scripts.ScriptDB'].objects.get(dbid) + dbobj = orm['scripts.ScriptDB'].objects.get(id=dbid) except: - print "could not find objid %i" % objid + print "could not find objid %i" % dbid continue else: print "Wrong object type to store on: %s" % typ continue - dbattr = orm['typeclasses.Attribute'].create(db_key=tmpattr.db_key, - db_value=tmpattr.db_value, - db_lock_storage=tmpattr.db_lock_storage, - db_date_created=tmpattr.db_date) + dbattr = orm['typeclasses.Attribute'](db_key=tmpattr.db_key, + db_value=tmpattr.db_value, + db_lock_storage=tmpattr.db_lock_storage, + db_date_created=tmpattr.db_date_created) dbattr.save() dbobj.db_attributes.add(dbattr) @@ -49,6 +52,42 @@ class Migration(DataMigration): raise RuntimeError("Cannot revert this migration.") models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, u'server.serverconfig': { 'Meta': {'object_name': 'ServerConfig'}, 'db_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}), @@ -72,8 +111,76 @@ class Migration(DataMigration): 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'objects.alias': { + 'Meta': {'object_name': 'Alias'}, + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['objects.ObjectDB']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'objects.objectdb': { + 'Meta': {'object_name': 'ObjectDB'}, + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destinations_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_home': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'homes_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_location': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locations_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']", 'null': 'True', 'blank': 'True'}), + 'db_sessid': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'objects.objectnick': { + 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'ObjectNick'}, + 'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['objects.ObjectDB']"}), + 'db_real': ('django.db.models.fields.TextField', [], {}), + 'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'players.playerdb': { + 'Meta': {'object_name': 'PlayerDB'}, + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'}) + }, + u'players.playernick': { + 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, + 'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}), + 'db_real': ('django.db.models.fields.TextField', [], {}), + 'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'scripts.scriptdb': { + 'Meta': {'object_name': 'ScriptDB'}, + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_desc': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_interval': ('django.db.models.fields.IntegerField', [], {'default': '-1'}), + 'db_is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['objects.ObjectDB']", 'null': 'True', 'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_persistent': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_repeats': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'db_start_delay': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) } } - complete_apps = ['server', 'typeclasses'] + complete_apps = ['server', 'typeclasses', 'objects', 'scripts', 'players'] symmetrical = True From 9e10a41e18992dfbf15b9a35715cf7a80485ff46 Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 11 Jul 2013 15:59:03 +0200 Subject: [PATCH 21/49] First version with all caches seemingly working ok. Started to remove the on-model wrappers that are not handled by the idmapper metaclass. --- src/comms/models.py | 2 - src/help/models.py | 123 +++++++++++++++++----------------- src/objects/admin.py | 2 +- src/objects/models.py | 10 ++- src/players/models.py | 11 ++-- src/scripts/models.py | 9 ++- src/server/caches.py | 4 +- src/server/models.py | 3 - src/typeclasses/models.py | 131 +++++++++++++++++-------------------- src/utils/idmapper/base.py | 14 ++-- 10 files changed, 144 insertions(+), 165 deletions(-) diff --git a/src/comms/models.py b/src/comms/models.py index 187ddf4b99..2c039d7283 100644 --- a/src/comms/models.py +++ b/src/comms/models.py @@ -303,8 +303,6 @@ class Msg(SharedMemoryModel): 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) - _db_model_name = "msg" # used by attributes to safely store objects - # # Msg class methods # diff --git a/src/help/models.py b/src/help/models.py index e61474e67d..8890009004 100644 --- a/src/help/models.py +++ b/src/help/models.py @@ -45,7 +45,7 @@ class HelpEntry(SharedMemoryModel): # These database fields are all set using their corresponding properties, # named same as the field, but withtout the db_* prefix. - # title of the help + # 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", @@ -72,9 +72,6 @@ class HelpEntry(SharedMemoryModel): verbose_name = "Help Entry" verbose_name_plural = "Help Entries" - # used by Attributes to safely retrieve stored object - _db_model_name = "helpentry" - # 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() @@ -85,53 +82,53 @@ class HelpEntry(SharedMemoryModel): # 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) + #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) + ## 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) + ## 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 @@ -153,20 +150,20 @@ class HelpEntry(SharedMemoryModel): 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) + ##@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) # diff --git a/src/objects/admin.py b/src/objects/admin.py index 2e7a9448de..70ee844cb2 100644 --- a/src/objects/admin.py +++ b/src/objects/admin.py @@ -6,7 +6,7 @@ from django import forms from django.conf import settings from django.contrib import admin -from src.typeclases.models import Attribute +from src.typeclasses.models import Attribute from src.objects.models import ObjectDB, ObjectNick, Alias from src.utils.utils import mod_import diff --git a/src/objects/models.py b/src/objects/models.py index 78f928fe21..bf7e565fcb 100644 --- a/src/objects/models.py +++ b/src/objects/models.py @@ -187,8 +187,11 @@ class ObjectDB(TypedObject): # Database manager objects = ObjectManager() - # Add the object-specific handlers + # caches for quick lookups of typeclass loading. + _typeclass_paths = settings.OBJECT_TYPECLASS_PATHS + _default_typeclass_path = settings.BASE_OBJECT_TYPECLASS or "src.objects.objects.Object" + # Add the object-specific handlers def __init__(self, *args, **kwargs): "Parent must be initialized first." TypedObject.__init__(self, *args, **kwargs) @@ -495,11 +498,6 @@ class ObjectDB(TypedObject): # ObjectDB class access methods/properties # - # this is required to properly handle attributes and typeclass loading. - _typeclass_paths = settings.OBJECT_TYPECLASS_PATHS - #_attribute_class = ObjAttribute - _db_model_name = "objectdb" # used by attributes to safely store objects - _default_typeclass_path = settings.BASE_OBJECT_TYPECLASS or "src.objects.objects.Object" #@property def __sessions_get(self): diff --git a/src/players/models.py b/src/players/models.py index be090531c8..7b7a3f04c9 100644 --- a/src/players/models.py +++ b/src/players/models.py @@ -137,11 +137,15 @@ class PlayerDB(TypedObject): db_is_connected = models.BooleanField(default=False, verbose_name="is_connected", help_text="If player is connected to game or not") # database storage of persistant cmdsets. db_cmdset_storage = models.CharField('cmdset', max_length=255, null=True, - help_text="optional python path to a cmdset class. If creating a Character, this will default to settings.CMDSET_CHARACTER.") + help_text="optional python path to a cmdset class. If creating a Character, this will default to settings.CMDSET_CHARACTER.") # Database manager objects = manager.PlayerManager() + # caches for quick lookups + _typeclass_paths = settings.PLAYER_TYPECLASS_PATHS + _default_typeclass_path = settings.BASE_PLAYER_TYPECLASS or "src.players.player.Player" + class Meta: app_label = 'players' verbose_name = 'Player' @@ -229,11 +233,6 @@ class PlayerDB(TypedObject): def __unicode__(self): return u"%s(player#%s)" % (_GA(self, "name"), _GA(self, "dbid")) - # this is required to properly handle attributes and typeclass loading - _typeclass_paths = settings.PLAYER_TYPECLASS_PATHS - #_attribute_class = PlayerAttribute - _db_model_name = "playerdb" # used by attributes to safely store objects - _default_typeclass_path = settings.BASE_PLAYER_TYPECLASS or "src.players.player.Player" # name property (wraps self.user.username) #@property diff --git a/src/scripts/models.py b/src/scripts/models.py index d275dd5fe1..cc29d96580 100644 --- a/src/scripts/models.py +++ b/src/scripts/models.py @@ -96,6 +96,10 @@ class ScriptDB(TypedObject): # Database manager objects = ScriptManager() + # caches for quick lookups + _typeclass_paths = settings.SCRIPT_TYPECLASS_PATHS + _default_typeclass_path = settings.BASE_SCRIPT_TYPECLASS or "src.scripts.scripts.DoNothing" + class Meta: "Define Django meta options" verbose_name = "Script" @@ -233,11 +237,6 @@ class ScriptDB(TypedObject): # # - # this is required to properly handle attributes and typeclass loading - _typeclass_paths = settings.SCRIPT_TYPECLASS_PATHS - #_attribute_class = ScriptAttribute - _db_model_name = "scriptdb" # used by attributes to safely store objects - _default_typeclass_path = settings.BASE_SCRIPT_TYPECLASS or "src.scripts.scripts.DoNothing" def at_typeclass_error(self): """ diff --git a/src/server/caches.py b/src/server/caches.py index e93cc5da67..b4d2707001 100644 --- a/src/server/caches.py +++ b/src/server/caches.py @@ -90,7 +90,7 @@ def field_pre_save(sender, instance=None, update_fields=None, raw=False, **kwarg """ if raw: return - print "field_pre_save:", instance, update_fields# if hasattr(instance, "db_key") else instance, update_fields + #print "field_pre_save:", instance, update_fields# if hasattr(instance, "db_key") else instance, update_fields if update_fields: # this is a list of strings at this point. We want field objects update_fields = (_GA(_GA(instance, "_meta"), "get_field_by_name")(field)[0] for field in update_fields) @@ -166,7 +166,7 @@ def post_attr_update(sender, **kwargs): obj = kwargs['instance'] model = kwargs['model'] action = kwargs['action'] - print "update_attr_cache:", obj, model, action + #print "update_attr_cache:", obj, model, action if kwargs['reverse']: # the reverse relation changed (the Attribute itself was acted on) pass diff --git a/src/server/models.py b/src/server/models.py index 4bb11c1bf1..da4ae08016 100644 --- a/src/server/models.py +++ b/src/server/models.py @@ -48,9 +48,6 @@ class ServerConfig(SharedMemoryModel): objects = ServerConfigManager() - # used by Attributes eventually storing this safely - _db_model_name = "serverconfig" - # 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() diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index 631506fd82..f224f5d4f2 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -401,29 +401,29 @@ class TypedObject(SharedMemoryModel): # TypedObject Database Model setup # # - # These databse fields are all set using their corresponding properties, - # named same as the field, but withtou the db_* prefix. + # These databse fields are all accessed and set using their corresponding properties, + # named same as the field, but without the db_* prefix (no separate save() call is needed) - # Main identifier of the object, for searching. Can also - # be referenced as 'name'. + # Main identifier of the object, for searching. Is accessed with self.key or self.name db_key = models.CharField('key', max_length=255, db_index=True) - # This is the python path to the type class this object is tied to - # (the type class is what defines what kind of Object this is) - db_typeclass_path = models.CharField('typeclass', max_length=255, null=True, help_text="this defines what 'type' of entity this is. This variable holds a Python path to a module with a valid Evennia Typeclass.") - # Creation date + # This is the python path to the type class this object is tied to the type class is what defines what kind of Object this is) + db_typeclass_path = models.CharField('typeclass', max_length=255, null=True, + help_text="this defines what 'type' of entity this is. This variable holds a Python path to a module with a valid Evennia Typeclass.") + # Creation date. This is not changed once the object is created. db_date_created = models.DateTimeField('creation date', editable=False, auto_now_add=True) # Permissions (access these through the 'permissions' property) - db_permissions = models.CharField('permissions', max_length=255, blank=True, help_text="a comma-separated list of text strings checked by certain locks. They are often used for hierarchies, such as letting a Player have permission 'Wizards', 'Builders' etc. Character objects use 'Players' by default. Most other objects don't have any permissions.") + db_permissions = models.CharField('permissions', max_length=255, blank=True, + help_text="a comma-separated list of text strings checked by in-game locks. They are often used for hierarchies, such as letting a Player have permission 'Wizards', 'Builders' etc. Character objects use 'Players' by default. Most other objects don't have any permissions.") # Lock storage - db_lock_storage = models.TextField('locks', blank=True, help_text="locks limit access to an entity. A lock is defined as a 'lock string' on the form 'type:lockfunctions', defining what functionality is locked and how to determine access. Not defining a lock means no access is granted.") - - # attribute store - db_attributes = models.ManyToManyField(Attribute, null=True, help_text='attributes on this object. An attribute can hold any pickle-able python object (see docs for special cases).') - + db_lock_storage = models.TextField('locks', blank=True, + help_text="locks limit access to an entity. A lock is defined as a 'lock string' on the form 'type:lockfunctions', defining what functionality is locked and how to determine access. Not defining a lock means no access is granted.") + # attribute store. This is accessed through the self.db handler. + db_attributes = models.ManyToManyField(Attribute, null=True, + help_text='attributes on this object. An attribute can hold any pickle-able python object (see docs for special cases).') # Database manager objects = managers.TypedObjectManager() - # object cache and flags + # quick on-object typeclass cache for speed _cached_typeclass = None # lock handler self.locks @@ -441,6 +441,7 @@ class TypedObject(SharedMemoryModel): verbose_name = "Evennia Database Object" ordering = ['-db_date_created', 'id', 'db_typeclass_path', 'db_key'] + # wrapper # 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() @@ -449,7 +450,6 @@ class TypedObject(SharedMemoryModel): # 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): @@ -466,53 +466,44 @@ class TypedObject(SharedMemoryModel): # raise Exception("Cannot delete objectdb key!") #key = property(__key_get, __key_set, __key_del) - # name property (wraps db_key too - alias to self.key) - #@property - def __name_get(self): - "Getter. Allows for value = self.name" - return self.key - #@name.sette - def __name_set(self, value): - "Setter. Allows for self.name = value" - self.key = value - #@name.deleter - def __name_del(self): - "Deleter. Allows for del self.name" - raise Exception("Cannot delete name!") + # name property (alias to self.key) + def __name_get(self): return self.key + def __name_set(self, value): self.key = value + def __name_del(self): raise Exception("Cannot delete name") name = property(__name_get, __name_set, __name_del) - # typeclass_path property - we don't cache this. + # typeclass_path property - we manage this separately. #@property - def __typeclass_path_get(self): - "Getter. Allows for value = self.typeclass_path" - return _GA(self, "db_typeclass_path")#get_field_cache(self, "typeclass_path") - #@typeclass_path.setter - def __typeclass_path_set(self, value): - "Setter. Allows for self.typeclass_path = value" - _SA(self, "db_typeclass_path", value) - update_fields = ["db_typeclass_path"] if _GA(self, "_get_pk_val")(_GA(self, "_meta")) is not None else None - _GA(self, "save")(update_fields=update_fields) - #@typeclass_path.deleter - def __typeclass_path_del(self): - "Deleter. Allows for del self.typeclass_path" - self.db_typeclass_path = "" - _GA(self, "save")(update_fields=["db_typeclass_path"]) - typeclass_path = property(__typeclass_path_get, __typeclass_path_set, __typeclass_path_del) + #def __typeclass_path_get(self): + # "Getter. Allows for value = self.typeclass_path" + # return _GA(self, "db_typeclass_path") + ##@typeclass_path.setter + #def __typeclass_path_set(self, value): + # "Setter. Allows for self.typeclass_path = value" + # _SA(self, "db_typeclass_path", value) + # update_fields = ["db_typeclass_path"] if _GA(self, "_get_pk_val")(_GA(self, "_meta")) is not None else None + # _GA(self, "save")(update_fields=update_fields) + ##@typeclass_path.deleter + #def __typeclass_path_del(self): + # "Deleter. Allows for del self.typeclass_path" + # self.db_typeclass_path = "" + # _GA(self, "save")(update_fields=["db_typeclass_path"]) + #typeclass_path = property(__typeclass_path_get, __typeclass_path_set, __typeclass_path_del) # date_created property #@property - def __date_created_get(self): - "Getter. Allows for value = self.date_created" - return get_field_cache(self, "date_created") - #@date_created.setter - def __date_created_set(self, value): - "Setter. Allows for self.date_created = value" - raise Exception("Cannot change date_created!") - #@date_created.deleter - def __date_created_del(self): - "Deleter. Allows for del self.date_created" - raise Exception("Cannot delete date_created!") - date_created = property(__date_created_get, __date_created_set, __date_created_del) + #def __date_created_get(self): + # "Getter. Allows for value = self.date_created" + # return get_field_cache(self, "date_created") + ##@date_created.setter + #def __date_created_set(self, value): + # "Setter. Allows for self.date_created = value" + # raise Exception("Cannot change date_created!") + ##@date_created.deleter + #def __date_created_del(self): + # "Deleter. Allows for del self.date_created" + # raise Exception("Cannot delete date_created!") + #date_created = property(__date_created_get, __date_created_set, __date_created_del) # permissions property #@property @@ -537,18 +528,18 @@ class TypedObject(SharedMemoryModel): # lock_storage property (wraps db_lock_storage) #@property - def __lock_storage_get(self): - "Getter. Allows for value = self.lock_storage" - return get_field_cache(self, "lock_storage") - #@lock_storage.setter - def __lock_storage_set(self, value): - """Saves the lock_storagetodate. This is usually not called directly, but through self.lock()""" - set_field_cache(self, "lock_storage", value) - #@lock_storage.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) + #def __lock_storage_get(self): + # "Getter. Allows for value = self.lock_storage" + # return get_field_cache(self, "lock_storage") + ##@lock_storage.setter + #def __lock_storage_set(self, value): + # """Saves the lock_storage. This is usually not called directly, but through self.lock()""" + # set_field_cache(self, "lock_storage", value) + ##@lock_storage.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) @@ -560,8 +551,6 @@ class TypedObject(SharedMemoryModel): # these are identifiers for fast Attribute access and caching _typeclass_paths = settings.OBJECT_TYPECLASS_PATHS - _attribute_class = Attribute # replaced by relevant attribute class for child - _db_model_name = "typeclass" # used by attributes to safely store objects def __eq__(self, other): return other and hasattr(other, 'dbid') and self.dbid == other.dbid diff --git a/src/utils/idmapper/base.py b/src/utils/idmapper/base.py index 2b4e6ce460..10510e195f 100755 --- a/src/utils/idmapper/base.py +++ b/src/utils/idmapper/base.py @@ -87,18 +87,18 @@ class SharedMemoryModelBase(ModelBase): "Helper method to create property wrappers with unique names (must be in separate call)" def _get(cls, fname): "Wrapper for getting database field" - #print "_get wrapper:", fname, value, type(value) value = _GA(cls, fieldname) - if isinstance(value, (basestring, int, float, bool)): + if type(value) in (basestring, int, float, bool): return value elif hasattr(value, "typeclass"): return _GA(value, "typeclass") return value + def _set(cls, fname, value): "Wrapper for setting database field" if hasattr(value, "dbobj"): value = _GA(value, "dbobj") - else: + elif fname.isdigit() or fname.startswith("#"): # we also allow setting using dbrefs, if so we try to load the matching object. # (we assume the object is of the same type as the class holding the field, if # not a custom handler must be used for that field) @@ -107,25 +107,27 @@ class SharedMemoryModelBase(ModelBase): try: value = cls._default_manager.get(id=dbid) except ObjectDoesNotExist: - err = "Could not set %s. Tried to treat value '%s' as a dbref, but no matching object with that id was found." - err = err % (fname, value) - raise ObjectDoesNotExist(err) + # maybe it is just a name + pass #print "_set wrapper:", fname, value, type(value), cls._get_pk_val(cls._meta) _SA(cls, fname, value) # only use explicit update_fields in save if we actually have a # primary key assigned already (won't be when first creating object) update_fields = [fname] if _GA(cls, "_get_pk_val")(_GA(cls, "_meta")) is not None else None _GA(cls, "save")(update_fields=update_fields) + def _del(cls, fname): "Wrapper for clearing database field - sets it to None" _SA(cls, fname, None) update_fields = [fname] if _GA(cls, "_get_pk_val")(_GA(cls, "_meta")) is not None else None _GA(cls, "save")(update_fields=update_fields) + # create class wrappers fget = lambda cls: _get(cls, fieldname) fset = lambda cls, val: _set(cls, fieldname, val) fdel = lambda cls: _del(cls, fieldname) doc = "Wraps setting, saving and deleting the %s field." % fieldname + type(cls).__setattr__(cls, wrappername, property(fget, fset, fdel, doc)) # exclude some models that should not auto-create wrapper fields From 46d1c48a389b33d7243891271867347b671aef55 Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 11 Jul 2013 18:03:07 +0200 Subject: [PATCH 22/49] Working implementation of User->PlayerDB conversion. Superuser must be created separately. The player-create method was corrected, along with the most obvious places where the user-setup was used. One can log in and look around but it's not heavily debugged yet. --- src/commands/default/unloggedin.py | 5 +- src/objects/manager.py | 28 +------ src/players/admin.py | 1 + src/players/manager.py | 71 +++------------- src/server/initial_setup.py | 28 ++++--- src/server/serversession.py | 11 ++- src/utils/create.py | 129 ++++++++++------------------- src/utils/search.py | 4 +- 8 files changed, 81 insertions(+), 196 deletions(-) diff --git a/src/commands/default/unloggedin.py b/src/commands/default/unloggedin.py index d9c5145f7c..f4f734ca5c 100644 --- a/src/commands/default/unloggedin.py +++ b/src/commands/default/unloggedin.py @@ -4,7 +4,6 @@ Commands that are available from the connect screen. import re import traceback from django.conf import settings -from django.contrib.auth.models import User from src.players.models import PlayerDB from src.objects.models import ObjectDB from src.server.models import ServerConfig @@ -68,7 +67,7 @@ class CmdUnconnectedConnect(MuxCommand): player = PlayerDB.objects.get_player_from_name(playername) pswd = None if player: - pswd = player.user.check_password(password) + pswd = player.check_password(password) if not (player and pswd): # No playername or password match @@ -142,7 +141,7 @@ class CmdUnconnectedCreate(MuxCommand): return # strip excessive spaces in playername playername = re.sub(r"\s+", " ", playername).strip() - if PlayerDB.objects.filter(user__username__iexact=playername) or User.objects.filter(username__iexact=playername): + if PlayerDB.objects.filter(username__iexact=playername): # player already exists (we also ignore capitalization here) session.msg("Sorry, there is already a player with the name '%s'." % playername) return diff --git a/src/objects/manager.py b/src/objects/manager.py index 0e8d0bbc57..d45e4b4d7e 100644 --- a/src/objects/manager.py +++ b/src/objects/manager.py @@ -34,7 +34,6 @@ class ObjectManager(TypedObjectManager): get_dbref_range object_totals typeclass_search - get_object_with_user get_object_with_player get_objs_with_key_and_typeclass get_objs_with_attr @@ -52,29 +51,8 @@ class ObjectManager(TypedObjectManager): # ObjectManager Get methods # - # user/player related + # player related - @returns_typeclass - def get_object_with_user(self, user): - """ - Matches objects with obj.player.user matching the argument. - A player<->user is a one-to-relationship, so this always - returns just one result or None. - - user - may be a user object or user id. - """ - dbref = self.dbref(user) - if dbref: - try: - return self.get(db_player__user__id=dbref) - except self.model.DoesNotExist: - pass - try: - return self.get(db_player__user=user) - except self.model.DoesNotExist: - return None - - # This returns typeclass since get_object_with_user and get_dbref does. @returns_typeclass def get_object_with_player(self, ostring, exact=True, candidates=None): """ @@ -92,9 +70,9 @@ class ObjectManager(TypedObjectManager): # not a dbref. Search by name. cand_restriction = candidates and Q(pk__in=[_GA(obj, "id") for obj in make_iter(candidates) if obj]) or Q() if exact: - return self.filter(cand_restriction & Q(db_player__user__username__iexact=ostring)) + return self.filter(cand_restriction & Q(db_player__username__iexact=ostring)) else: # fuzzy matching - ply_cands = self.filter(cand_restriction & Q(playerdb__user__username__istartswith=ostring)).values_list("db_key", flat=True) + ply_cands = self.filter(cand_restriction & Q(playerdb__username__istartswith=ostring)).values_list("db_key", flat=True) if candidates: index_matches = string_partial_matching(ply_cands, ostring, ret_index=True) return [obj for ind, obj in enumerate(make_iter(candidates)) if ind in index_matches] diff --git a/src/players/admin.py b/src/players/admin.py index 64e8e3d36b..b61b36f60a 100644 --- a/src/players/admin.py +++ b/src/players/admin.py @@ -141,6 +141,7 @@ class UserAdmin(BaseUserAdmin): {'fields': ('username', 'password1', 'password2', 'email'), 'description':"These account details are shared by the admin system and the game."},),) + # TODO! Remove User reference! def save_formset(self, request, form, formset, change): "Run all hooks on the player object" super(UserAdmin, self).save_formset(request, form, formset, change) diff --git a/src/players/manager.py b/src/players/manager.py index b95c96284b..4bfc9605b0 100644 --- a/src/players/manager.py +++ b/src/players/manager.py @@ -3,8 +3,8 @@ The managers for the custom Player object and permissions. """ import datetime -from functools import update_wrapper from django.contrib.auth.models import UserManager +from functools import update_wrapper from src.typeclasses.managers import returns_typeclass_list, returns_typeclass, TypedObjectManager from src.utils import logger __all__ = ("PlayerManager",) @@ -13,53 +13,6 @@ __all__ = ("PlayerManager",) # Player Manager # -def returns_player_list(method): - """ - decorator that makes sure that a method - returns a Player object instead of a User - one (if you really want the User object, not - the player, use the player's 'user' property) - """ - def func(self, *args, **kwargs): - "This *always* returns a list." - match = method(self, *args, **kwargs) - if not match: - return [] - try: - match = list(match) - except TypeError: - match = [match] - players = [] - for user in match: - try: - players.append(user.get_profile()) - except Exception: - # there is something wrong with get_profile. But - # there is a 1-1 relation between Users-Players, so we - # try to go the other way instead. - from src.players.models import PlayerDB - match = PlayerDB.objects.filter(user__id=user.id) - if match: - players.append(match[0]) - else: - logger.log_trace("No connection User<->Player, maybe database was partially reset?") - return players - return update_wrapper(func, method) - -def returns_player(method): - """ - Decorator: Always returns a single result or None. - """ - def func(self, *args, **kwargs): - "decorator" - rfunc = returns_player_list(method) - match = rfunc(self, *args, **kwargs) - if match: - return match[0] - else: - return None - return update_wrapper(func, method) - class PlayerManager(TypedObjectManager, UserManager): """ This PlayerManager implements methods for searching @@ -87,7 +40,7 @@ class PlayerManager(TypedObjectManager, UserManager): """ def num_total_players(self): """ - Returns the total number of registered users/players. + Returns the total number of registered players. """ return self.count() @@ -99,7 +52,6 @@ class PlayerManager(TypedObjectManager, UserManager): return self.filter(db_is_connected=True) @returns_typeclass_list - @returns_player_list def get_recently_created_players(self, days=7): """ Returns a QuerySet containing the player User accounts that have been @@ -108,13 +60,12 @@ class PlayerManager(TypedObjectManager, UserManager): end_date = datetime.datetime.now() tdelta = datetime.timedelta(days) start_date = end_date - tdelta - return User.objects.filter(date_joined__range=(start_date, end_date)) + return self.filter(date_joined__range=(start_date, end_date)) @returns_typeclass_list - @returns_player_list def get_recently_connected_players(self, days=7): """ - Returns a QuerySet containing the player User accounts that have been + Returns a QuerySet containing the player accounts that have been connected within the last days. days - number of days backwards to check @@ -122,33 +73,31 @@ class PlayerManager(TypedObjectManager, UserManager): end_date = datetime.datetime.now() tdelta = datetime.timedelta(days) start_date = end_date - tdelta - return User.objects.filter(last_login__range=( + return self.filter(last_login__range=( start_date, end_date)).order_by('-last_login') @returns_typeclass - @returns_player def get_player_from_email(self, uemail): """ Returns a player object when given an email address. """ - return User.objects.filter(email__iexact=uemail) + return self.filter(email__iexact=uemail) @returns_typeclass - @returns_player def get_player_from_uid(self, uid): """ Returns a player object based on User id. """ try: - return User.objects.get(id=uid) - except User.model.DoesNotExist: + return self.get(id=uid) + except self.model.DoesNotExist: return None @returns_typeclass def get_player_from_name(self, uname): "Get player object based on name" try: - return self.get(user__username__iexact=uname) + return self.get(username__iexact=uname) except self.model.DoesNotExist: return None @@ -165,7 +114,7 @@ class PlayerManager(TypedObjectManager, UserManager): matches = self.filter(id=dbref) if matches: return matches - return self.filter(user__username__iexact=ostring) + return self.filter(username__iexact=ostring) def swap_character(self, player, new_character, delete_old_character=False): """ diff --git a/src/server/initial_setup.py b/src/server/initial_setup.py index f93da77d5b..feaca4ec33 100644 --- a/src/server/initial_setup.py +++ b/src/server/initial_setup.py @@ -25,20 +25,20 @@ def create_config_values(): ServerConfig.objects.conf("site_name", settings.SERVERNAME) ServerConfig.objects.conf("idle_timeout", settings.IDLE_TIMEOUT) -def get_god_user(): +def get_god_player(): """ Creates the god user. """ PlayerDB = get_user_model() try: - god_user = PlayerDB.objects.get(id=1) + god_player = PlayerDB.objects.get(id=1) except PlayerDB.DoesNotExist: txt = "\n\nNo superuser exists yet. The superuser is the 'owner' account on the" - txt += "\nEvennia server; a good safety fallback. Create a new superuser using the command" + txt += "\nEvennia server. Create a new superuser using the command" txt += "\n\n python manage.py createsuperuser" txt += "\n\nFollow the prompts, then restart the server." raise Exception(txt) - return god_user + return god_player def create_objects(): """ @@ -49,22 +49,26 @@ def create_objects(): # Set the initial User's account object's username on the #1 object. # This object is pure django and only holds name, email and password. - god_user = get_god_user() + god_player = get_god_player() # Create a Player 'user profile' object to hold eventual # mud-specific settings for the bog standard User object. This is # accessed by user.get_profile() and can also store attributes. # It also holds mud permissions, but for a superuser these # have no effect anyhow. - character_typeclass = settings.BASE_CHARACTER_TYPECLASS + player_typeclass = settings.BASE_PLAYER_TYPECLASS - # Create the Player object as well as the in-game god-character - # for user #1. We can't set location and home yet since nothing + # run all creation hooks on god_player (we must do so manually since the manage.py command does not) + god_player.typeclass_path = player_typeclass + god_player.basetype_setup() + god_player.at_player_creation() + god_player.locks.add("examine:perm(Immortals);edit:false();delete:false();boot:false();msg:all()") + + # Create the in-game god-character for player #1. We can't set location and home yet since nothing # exists. Also, all properties (name, email, password, is_superuser) # is inherited from the user so we don't specify it again here. - - god_player = create.create_player(god_user.username, None, None, user=god_user) - god_character = create.create_object(character_typeclass, key=god_user.username) + character_typeclass = settings.BASE_CHARACTER_TYPECLASS + god_character = create.create_object(character_typeclass, key=god_player.username) god_character.id = 1 god_character.db.desc = _('This is User #1.') @@ -132,7 +136,7 @@ def create_channels(): return # connect the god user to all these channels by default. - goduser = get_god_user() + goduser = get_god_player() from src.comms.models import PlayerChannelConnection PlayerChannelConnection.objects.create_connection(goduser, pchan) PlayerChannelConnection.objects.create_connection(goduser, ichan) diff --git a/src/server/serversession.py b/src/server/serversession.py index 49493311f8..24ba73cae1 100644 --- a/src/server/serversession.py +++ b/src/server/serversession.py @@ -77,17 +77,16 @@ class ServerSession(Session): player - the player associated with the session """ self.player = player - self.user = player.user - self.uid = self.user.id - self.uname = self.user.username + 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 # Update account's last login time. - self.user.last_login = datetime.now() - self.user.save() + self.player.last_login = datetime.now() + self.player.save() def at_disconnect(self): """ @@ -97,7 +96,7 @@ class ServerSession(Session): sessid = self.sessid player = self.player _GA(player.dbobj, "unpuppet_object")(sessid) - uaccount = _GA(player.dbobj, "user") + uaccount = player.dbobj uaccount.last_login = datetime.now() uaccount.save() # calling player hook diff --git a/src/utils/create.py b/src/utils/create.py index 0eae842304..32e07dfa7c 100644 --- a/src/utils/create.py +++ b/src/utils/create.py @@ -22,7 +22,6 @@ Models covered: Players """ from django.conf import settings -from django.contrib.auth.models import User from django.db import IntegrityError from src.utils.idmapper.models import SharedMemoryModel from src.utils import utils, logger @@ -387,49 +386,32 @@ channel = create_channel # Player creation methods # -def create_player(name, email, password, - user=None, +def create_player(key, email, password, typeclass=None, is_superuser=False, locks=None, permissions=None, - player_dbobj=None, report_to=None): + report_to=None): """ - This creates a new player, handling the creation of the User - object and its associated Player object. + This creates a new player. - If player_dbobj is given, this player object is used instead of - creating a new one. This is called by the admin interface since it - needs to create the player object in order to relate it automatically - to the user. + key - the player's name. This should be unique. + email - email on valid addr@addr.domain form. + password - password in cleartext + is_superuser - wether or not this player is to be a superuser + locks - lockstring + permission - list of permissions + report_to - an object with a msg() method to report errors to. If + not given, errors will be logged. - If create_character is - True, a game player object with the same name as the User/Player will - also be created. Its typeclass and base properties can also be given. - - Returns the new game character, or the Player obj if no - character is created. For more info about the typeclass argument, - see create_objects() above. - - Note: if user is supplied, it will NOT be modified (args name, email, - passw and is_superuser will be ignored). Change those properties - directly on the User instead. - - If no permissions are given (None), the default permission group - as defined in settings.PERMISSION_PLAYER_DEFAULT will be - assigned. If permissions are given, no automatic assignment will - occur. + Will return the Player-typeclass or None/raise Exception if the + Typeclass given failed to load. Concerning is_superuser: - A superuser should have access to everything - in the game and on the server/web interface. The very first user - created in the database is always a superuser (that's using - django's own creation, not this one). Usually only the server admin should need to be superuser, all other access levels can be handled with more fine-grained - permissions or groups. - Since superuser overrules all permissions, we don't - set any in this case. + permissions or groups. A superuser bypasses all lock checking + operations and is thus not suitable for play-testing the game. """ global _PlayerDB, _Player @@ -440,48 +422,28 @@ def create_player(name, email, password, if not email: email = "dummy@dummy.com" - if user: - new_user = user - email = user.email - - if user: - conflict_check = User.objects.filter(username__iexact=user.username) - conflict_check = len(conflict_check) > 1 - else: - conflict_check = User.objects.filter(username__iexact=name) - - if conflict_check: - raise ValueError("A user with this name already exists.") - - if not user: - if is_superuser: - new_user = User.objects.create_superuser(name, email, password) - else: - new_user = User.objects.create_user(name, email, password) + if _PlayerDB.objects.filter(username__iexact=key): + raise ValueError("A Player with this name already exists.") try: + + # create the correct Player object + if is_superuser: + new_db_player = _PlayerDB.objects.create_superuser(key, email, password) + else: + new_db_player = _PlayerDB.objects.create_user(key, email, password) + if not typeclass: typeclass = settings.BASE_PLAYER_TYPECLASS elif isinstance(typeclass, _PlayerDB): - # this is already an objectdb instance, extract its typeclass + # this is an PlayerDB instance, extract its typeclass path typeclass = typeclass.typeclass.path elif isinstance(typeclass, _Player) or utils.inherits_from(typeclass, _Player): - # this is already an object typeclass, extract its path + # this is Player object typeclass, extract its path typeclass = typeclass.path - if player_dbobj: - try: - _GA(player_dbobj, "dbobj") - new_db_player = player_dbobj.dbobj - except AttributeError: - new_db_player = player_dbobj - # use the typeclass from this object - typeclass = new_db_player.typeclass_path - else: - new_user = User.objects.get(username=new_user.username) - new_db_player = _PlayerDB(db_key=name, user=new_user) - new_db_player.save() - # assign the typeclass - typeclass = utils.to_unicode(typeclass) - new_db_player.typeclass_path = typeclass + + # assign the typeclass + typeclass = utils.to_unicode(typeclass) + new_db_player.typeclass_path = typeclass # this will either load the typeclass or the default one new_player = new_db_player.typeclass @@ -500,34 +462,27 @@ def create_player(name, email, password, # call hook method (may override default permissions) new_player.at_player_creation() - print # custom given arguments potentially overrides the hook if permissions: new_player.permissions = permissions elif not new_player.permissions: new_player.permissions = settings.PERMISSION_PLAYER_DEFAULT - if locks: new_player.locks.add(locks) - return new_player + except Exception: - # a failure in creating the character - if not user: - # in there was a failure we clean up everything we can - logger.log_trace() - try: - new_user.delete() - except Exception: - pass - try: - new_player.delete() - except Exception: - pass - try: - del new_player - except Exception: - pass + # a failure in creating the player; we try to clean + # up as much as we can + logger.log_trace() + try: + new_player.delete() + except Exception: + pass + try: + del new_player + except Exception: + pass raise # alias diff --git a/src/utils/search.py b/src/utils/search.py index a7abbc2354..032c6241d1 100644 --- a/src/utils/search.py +++ b/src/utils/search.py @@ -16,11 +16,11 @@ the database model and call its 'objects' property. Also remember that all commands in this file return lists (also if there is only one match) unless noted otherwise. -Example: To reach the search method 'get_object_with_user' +Example: To reach the search method 'get_object_with_player' in src/objects/managers.py: > from src.objects.models import ObjectDB -> match = Object.objects.get_object_with_user(...) +> match = Object.objects.get_object_with_player(...) """ From a4042920e00ca77758106e79de1bb771fc8bd23a Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 11 Jul 2013 22:24:55 +0200 Subject: [PATCH 23/49] Fixed the migrations to get to a baseline version you can log into. --- .../0020_auto__del_playerattribute.py | 2 +- .../migrations/0021_add_playerdbtmp.py | 25 +++---- .../0022_copy_user_profile_to_tmp.py | 21 +++--- .../migrations/0023_delete_old_profile.py | 25 +++---- ...ayerdb.py => 0024_rename_tmp_to_player.py} | 66 ++++++++++--------- src/players/models.py | 6 -- src/utils/idmapper/base.py | 2 + 7 files changed, 75 insertions(+), 72 deletions(-) rename src/players/migrations/{0024_rename_tmp_player_to_playerdb.py => 0024_rename_tmp_to_player.py} (64%) diff --git a/src/players/migrations/0020_auto__del_playerattribute.py b/src/players/migrations/0020_auto__del_playerattribute.py index d58c9324df..6f7b456cf6 100644 --- a/src/players/migrations/0020_auto__del_playerattribute.py +++ b/src/players/migrations/0020_auto__del_playerattribute.py @@ -104,4 +104,4 @@ class Migration(SchemaMigration): } } - complete_apps = ['players'] \ No newline at end of file + complete_apps = ['players'] diff --git a/src/players/migrations/0021_add_playerdbtmp.py b/src/players/migrations/0021_add_playerdbtmp.py index 8a51877312..85e503b327 100644 --- a/src/players/migrations/0021_add_playerdbtmp.py +++ b/src/players/migrations/0021_add_playerdbtmp.py @@ -105,17 +105,9 @@ class Migration(SchemaMigration): 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) }, - u'players.playerattribute': { - 'Meta': {'object_name': 'PlayerAttribute'}, - 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), - 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}), - 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) - }, u'players.playerdb': { 'Meta': {'object_name': 'PlayerDB'}, + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), @@ -129,10 +121,11 @@ class Migration(SchemaMigration): u'players.playerdbtmp': { 'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDBtmp'}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), - 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), @@ -149,6 +142,14 @@ class Migration(SchemaMigration): 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) }, + u'typeclasses.attribute': { + 'Meta': {'object_name': 'Attribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, u'players.playernick': { 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, 'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), diff --git a/src/players/migrations/0022_copy_user_profile_to_tmp.py b/src/players/migrations/0022_copy_user_profile_to_tmp.py index 030e6d21e8..2ea41dc715 100644 --- a/src/players/migrations/0022_copy_user_profile_to_tmp.py +++ b/src/players/migrations/0022_copy_user_profile_to_tmp.py @@ -11,6 +11,7 @@ class Migration(DataMigration): # Note: Remember to use orm['appname.ModelName'] rather than "from appname.models..." if not db.dry_run: for profile in orm['players.PlayerDB'].objects.all(): + print "player orig:", profile.db_key, profile.db_cmdset_storage plyr = orm['players.PlayerDBtmp'].objects.get(id=profile.user_id) plyr.db_cmdset_storage = profile.db_cmdset_storage plyr.db_date_created = profile.db_date_created @@ -62,17 +63,9 @@ class Migration(DataMigration): 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) }, - u'players.playerattribute': { - 'Meta': {'object_name': 'PlayerAttribute'}, - 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), - 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}), - 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) - }, u'players.playerdb': { 'Meta': {'object_name': 'PlayerDB'}, + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), @@ -86,6 +79,8 @@ class Migration(DataMigration): u'players.playerdbtmp': { 'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDBtmp'}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), @@ -104,6 +99,14 @@ class Migration(DataMigration): 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) }, + u'typeclasses.attribute': { + 'Meta': {'object_name': 'Attribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, u'players.playernick': { 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, 'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), diff --git a/src/players/migrations/0023_delete_old_profile.py b/src/players/migrations/0023_delete_old_profile.py index dd1f7c2dd8..5f84edeaf6 100644 --- a/src/players/migrations/0023_delete_old_profile.py +++ b/src/players/migrations/0023_delete_old_profile.py @@ -50,17 +50,9 @@ class Migration(SchemaMigration): 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) }, - u'players.playerattribute': { - 'Meta': {'object_name': 'PlayerAttribute'}, - 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), - 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}), - 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) - }, u'players.playerdb': { 'Meta': {'object_name': 'PlayerDB'}, + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), @@ -74,10 +66,11 @@ class Migration(SchemaMigration): u'players.playerdbtmp': { 'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDBtmp'}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), - 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), @@ -94,6 +87,14 @@ class Migration(SchemaMigration): 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) }, + u'typeclasses.attribute': { + 'Meta': {'object_name': 'Attribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, u'players.playernick': { 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, 'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), diff --git a/src/players/migrations/0024_rename_tmp_player_to_playerdb.py b/src/players/migrations/0024_rename_tmp_to_player.py similarity index 64% rename from src/players/migrations/0024_rename_tmp_player_to_playerdb.py rename to src/players/migrations/0024_rename_tmp_to_player.py index 1a942b8be1..85db97515e 100644 --- a/src/players/migrations/0024_rename_tmp_player_to_playerdb.py +++ b/src/players/migrations/0024_rename_tmp_to_player.py @@ -4,12 +4,11 @@ from south.db import db from south.v2 import SchemaMigration from django.db import models - class Migration(SchemaMigration): def forwards(self, orm): + db.rename_table('players_PlayerDBtmp', 'players_PlayerDB') - db.send_create_signal('players', ['PlayerDB']) def backwards(self, orm): raise RuntimeError("Cannot revert this migration.") @@ -35,42 +34,37 @@ class Migration(SchemaMigration): 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) }, - u'players.playerattribute': { - 'Meta': {'object_name': 'PlayerAttribute'}, + u'players.playerdb': { + 'Meta': {'object_name': 'PlayerDB'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}), - 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) }, -# u'players.playerdbtmp': { -# 'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDBtmp'}, -# 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), -# 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), -# 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), -# 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), -# 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), -# 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), -# 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), -# 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), -# 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), -# 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), -# 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), -# u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), -# 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), -# 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), -# 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), -# 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), -# 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), -# 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), -# 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), -# 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) -# }, - u'players.playerdb': { - 'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDB'}, + u'players.playerdbtmp': { + 'Meta': {'object_name': 'PlayerDBtmp'}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), @@ -95,6 +89,14 @@ class Migration(SchemaMigration): 'db_real': ('django.db.models.fields.TextField', [], {}), 'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.attribute': { + 'Meta': {'object_name': 'Attribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) } } diff --git a/src/players/models.py b/src/players/models.py index 42af97a888..ca10ebb574 100644 --- a/src/players/models.py +++ b/src/players/models.py @@ -129,10 +129,6 @@ class PlayerDB(TypedObject, AbstractUser): # inherited fields (from TypedObject): # db_key, db_typeclass_path, db_date_created, db_permissions - # this is the one-to-one link between the customized Player object and - # this profile model. It is required by django. - #user = models.ForeignKey(User, unique=True, db_index=True, - # help_text="The User object holds django-specific authentication for each Player. A unique User should be created and tied to each Player, the two should never be switched or changed around. The User will be deleted automatically when the Player is.") # store a connected flag here too, not just in sessionhandler. # This makes it easier to track from various out-of-process locations db_is_connected = models.BooleanField(default=False, verbose_name="is_connected", help_text="If player is connected to game or not") @@ -559,5 +555,3 @@ class PlayerDB(TypedObject, AbstractUser): pass return matches -class PlayerDBtmp(AbstractUser): - pass diff --git a/src/utils/idmapper/base.py b/src/utils/idmapper/base.py index 10510e195f..558d5f3d81 100755 --- a/src/utils/idmapper/base.py +++ b/src/utils/idmapper/base.py @@ -136,6 +136,8 @@ class SharedMemoryModelBase(ModelBase): # dynamically create the wrapper properties for all fields not already handled for field in cls._meta.fields: fieldname = field.name + if not fieldname.startswith("db_"): + continue wrappername = fieldname == "id" and "dbid" or fieldname.replace("db_", "") if not hasattr(cls, wrappername): # makes sure not to overload manually created wrappers on the model From 607674c6cf94d773c4d97890a5f1b458e71cd839 Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 11 Jul 2013 22:47:17 +0200 Subject: [PATCH 24/49] Added a superuser creation call to evennia.py to replace the automatic one that was done by syncdb before. --- game/evennia.py | 11 +++++++---- src/server/initial_setup.py | 1 - 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/game/evennia.py b/game/evennia.py index 958786d32f..a28616b3cf 100755 --- a/game/evennia.py +++ b/game/evennia.py @@ -129,11 +129,9 @@ PORTAL_LOGFILE = settings.PORTAL_LOG_FILE # Check so a database exists and is accessible from django.db import DatabaseError -from src.objects.models import ObjectDB +from src.players.models import PlayerDB try: - test = ObjectDB.objects.get(id=1) -except ObjectDB.DoesNotExist: - pass # this is fine at this point + superuser = PlayerDB.objects.get(id=1) except DatabaseError,e: print """ Your database does not seem to be set up correctly. @@ -147,6 +145,11 @@ except DatabaseError,e: When you have a database set up, rerun evennia.py. """ % e sys.exit() +except PlayerDB.DoesNotExist: + # no superuser yet. We need to create it. + from django.core.management import call_command + print "Create a superuser below. The superuser is Player #1, the 'owner' account of the server." + call_command("createsuperuser", interactive=True) # Add this to the environmental variable for the 'twistd' command. currpath = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) diff --git a/src/server/initial_setup.py b/src/server/initial_setup.py index feaca4ec33..c81a97965f 100644 --- a/src/server/initial_setup.py +++ b/src/server/initial_setup.py @@ -9,7 +9,6 @@ Everything starts at handle_setup() import django from django.core import management from django.conf import settings -from django.core.management import call_command from django.contrib.auth import get_user_model from src.server.models import ServerConfig from src.help.models import HelpEntry From e2ce3f22230de64a8ed4d27317948be0dc1ae7bf Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 11 Jul 2013 22:59:11 +0200 Subject: [PATCH 25/49] Minor formatting. --- game/evennia.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/game/evennia.py b/game/evennia.py index a28616b3cf..b17a97743c 100755 --- a/game/evennia.py +++ b/game/evennia.py @@ -148,7 +148,7 @@ except DatabaseError,e: except PlayerDB.DoesNotExist: # no superuser yet. We need to create it. from django.core.management import call_command - print "Create a superuser below. The superuser is Player #1, the 'owner' account of the server." + print "\nCreate a superuser below. The superuser is Player #1, the 'owner' account of the server.\n" call_command("createsuperuser", interactive=True) # Add this to the environmental variable for the 'twistd' command. From e17896394121c1d70785539fec50b2804a258a9f Mon Sep 17 00:00:00 2001 From: Griatch Date: Fri, 12 Jul 2013 11:12:21 +0200 Subject: [PATCH 26/49] First implementation of new Tags and LiteAttribute models to replace Aliases and Nicks while offering more flexibility. --- src/typeclasses/managers.py | 132 +++++++++++++++++++++++++++++++++++- src/typeclasses/models.py | 108 +++++++++++++++++++++++++++-- 2 files changed, 233 insertions(+), 7 deletions(-) diff --git a/src/typeclasses/managers.py b/src/typeclasses/managers.py index 28ddbe61cb..0ee0f0a21c 100644 --- a/src/typeclasses/managers.py +++ b/src/typeclasses/managers.py @@ -5,7 +5,7 @@ all Attributes and TypedObjects). """ from functools import update_wrapper from django.db import models -from django.contrib.contenttypes.models import ContentType +from django.db.models import Q from src.utils import idmapper from src.utils.utils import make_iter from src.utils.dbserialize import to_pickle @@ -50,7 +50,7 @@ class AttributeManager(models.Manager): def exists(self,*args, **kwargs): return super(AttributeManager, self).exists(*args, **kwargs) - def attr_namesearch(self, searchstr, obj, exact_match=True): + def get_attrs_on_obj(self, searchstr, obj, exact_match=True): """ Searches the object's attributes for attribute key matches. @@ -63,7 +63,11 @@ class AttributeManager(models.Manager): else: return _GA("obj", "db_attributes").filter(db_key__icontains=searchstr) - def attr_valuesearch(self, searchstr, obj=None): + def attr_namesearch(self, *args, **kwargs): + "alias wrapper for backwards compatability" + return self.get_attrs_on_obj(*args, **kwargs) + + def get_attr_by_value(self, searchstr, obj=None): """ Searches obj for Attributes with a given value. searchstr - value to search for. This may be any suitable object. @@ -78,6 +82,128 @@ class AttributeManager(models.Manager): return _GA(obj, "db_attributes").filter(db_value=searchstr) return self.filter(db_value=searchstr) + def attr_valuesearch(self, *args, **kwargs): + "alias wrapper for backwards compatability" + return self.get_attr_by_value(self, *args, **kwargs) + +# +# LiteAttributeManager +# + +class LiteAttributeManager(models.Manager): + """ + Manager methods for LiteAttributes + """ + def get_lattrs_on_obj(self, obj, search_key=None, category=None): + """ + Get all lattrs on obj, optionally limited by key and/or category + """ + if search_key or category: + key_cands = Q(db_key__iexact=search_key.lower().strip()) if search_key!=None else Q() + cat_cands = Q(db_category__iexact=category.lower.strip()) if search_key!=None else Q() + return _GA(obj, "db_tags").filter(cat_cands & key_cands) + else: + return list(_GA(obj, "db_tags").all()) + + def get_lattr(self, search_key=None, category=None): + """ + Search and return all liteattrs matching any combination of + the search criteria. + search_key (string) - the lattr identifier + category (string) - the lattr category + """ + key_cands = Q(db_key__iexact=search_key.lower().strip()) if search_key!=None else Q() + cat_cands = Q(db_category__iexact=category.lower.strip()) if search_key!=None else Q() + return list(self.filter(key_cands & cat_cands)) + + def get_lattr_data(self, obj=None, search_key=None, category=None): + """ + Retrieve data from found lattrs in an efficient way. Returns a list of data + matching the search criterions + """ + key_cands = Q(db_key__iexact=search_key.lower().strip()) if search_key!=None else Q() + cat_cands = Q(db_category__iexact=category.lower.strip()) if search_key!=None else Q() + if obj: + query = _GA(obj, "db_liteattributes").filter(key_cands & cat_cands).prefetch_related("db_data") + else: + query = self.filter(key_cands & cat_cands).prefetch_related("db_data") + return [q.db_data for q in query] + + def create_lattr(self, key, category=None, data=None, obj=None): + """ + Create a LiteAttribute. This makes sure the create case-insensitive keys. + """ + + lattr = self.objects.create(db_key=key.lower().strip(), + db_category=category.lower().strip() if category!=None else None, + db_data=str(data) if data!=None else None) + lattr.save() + if obj: + obj.db_liteattributes.add(lattr) + return lattr + +# +# TagManager +# + +class TagManager(models.Manager): + """ + Extra manager methods for Tags + """ + def get_tags_on_obj(self, obj, search_key=None, category=None): + """ + Get all tags on obj, optionally limited by key and/or category + """ + if search_key or category: + key_cands = Q(db_key__iexact=search_key.lower().strip()) if search_key!=None else Q() + cat_cands = Q(db_category__iexact=category.lower.strip()) if search_key!=None else Q() + return _GA(obj, "db_tags").filter(cat_cands & key_cands) + else: + return list(_GA(obj, "db_tags").all()) + + def get_tag(self, search_key=None, category=None): + """ + Search and return all tags matching any combination of + the search criteria. + search_key (string) - the tag identifier + category (string) - the tag category + """ + key_cands = Q(db_key__iexact=search_key.lower().strip()) if search_key!=None else Q() + cat_cands = Q(db_category__iexact=category.lower.strip()) if search_key!=None else Q() + return list(self.filter(key_cands & cat_cands)) + + def get_objs_with_tag(self, objclass, search_key=None, category=None): + """ + Search and return all objects of objclass that has tags matching + the given search criteria. + objclass (dbmodel) - the object class to search + search_key (string) - the tag identifier + category (string) - the tag category + """ + key_cands = Q(db_tags__db_key__iexact=search_key.lower().strip()) if search_key!=None else Q() + cat_cands = Q(db_tags__db_category__iexact=category.lower().strip()) if category!=None else Q() + return objclass.objects.filter(key_cands & cat_cands) + + def create_tag(self, key=None, category=None, data=None): + """ + Create a tag. This makes sure the create case-insensitive tags. + Note that if the exact same tag configuration (key+category) + exists, it will be re-used. A data keyword will overwrite existing + data on a tag (it is not part of what makes the tag unique). + + """ + data = str(data) if data!=None else None + + tag = self.get_tag(search_key=key, search_category=category) + if tag and data != None: + tag.db_data = data + tag.save() + elif not tag: + tag = self.objects.create(db_key=key.lower().strip() if key!=None else None, + db_category=category.lower().strip() if key!=None else None, + db_data=str(data) if data!=None else None) + tag.save() + return tag # # helper functions for the TypedObjectManager. diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index f224f5d4f2..26f929aae9 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -41,7 +41,7 @@ from django.contrib.contenttypes.models import ContentType from src.utils.idmapper.models import SharedMemoryModel from src.server.caches import get_field_cache, set_field_cache, del_field_cache from src.server.caches import get_attr_cache, set_attr_cache -from src.server.caches import get_prop_cache, set_prop_cache, del_prop_cache, flush_attr_cache +from src.server.caches import get_prop_cache, set_prop_cache, flush_attr_cache from django.db.models.signals import m2m_changed from src.server.caches import post_attr_update @@ -51,7 +51,7 @@ from src.server.models import ServerConfig from src.typeclasses import managers from src.locks.lockhandler import LockHandler from src.utils import logger, utils -from src.utils.utils import make_iter, is_iter, to_unicode, to_str +from src.utils.utils import make_iter, is_iter, to_str from src.utils.dbserialize import to_pickle, from_pickle from src.utils.picklefield import PickledObjectField @@ -252,6 +252,101 @@ class Attribute(SharedMemoryModel): """ pass +#------------------------------------------------------------ +# +# LiteAttributes +# +#------------------------------------------------------------ + +class LiteAttribute(models.Model): + + """ + This specialized model is a middle-road between a Tag + and an Attribute. A LiteAttribute is smaller, less complex + to search than an Attribute (its key is indexed together with its + category) but can only hold strings in its db_value property whereas + an Attribute can hold arbitrary data. A LiteAttribute is also not + kept in memory in the same way as Attributes and has no inherent + concept of access restrictions which makes it unsuitable for modification + by untrusted users. + + The difference between Liteattrs and Tags are that liteattrs are + not shared/unique but are created separately for each object holding them. + + LiteAttributes are accessed through the db_liteattributes many2many field on + Typed Objects. + + + The main default use of the LiteAttribute is to implement Nick replacement. + In this case the category determines when the replacement is to be checked. + The key value is the input to replace and the data value holds the replacement + text. + + The default nick category types used by Evennia are: + nick_inputline (default) - match against all input + nick_player - match against player searches + nick_obj - match against object searches + nick_channel - used to store own names for channels + + """ + db_key = models.CharField('key', max_length=255, help_text='name if liteattribute') + db_category = models.CharField('category', max_length=32, null=True, blank=True, help_text="liteattribute category") + db_data = models.TextField('data', help_text='holds string data') + + objects = managers.LiteAttributeManager() + + class Meta: + "Define Django meta options" + abstract = True + verbose_name = "Lite Attribute" + index_together = ("db_key", "db_category") + def __unicode__(self): + return u"%s" % self.db_key + def __str__(self): + return str(self.db_key) + +#------------------------------------------------------------ +# +# Tags +# +#------------------------------------------------------------ + +class Tag(models.Model): + """ + Tags are quick markers for objects in-game. An typeobject + can have any number of tags, stored via its db_tags property. + Tagging similar objects will make it easier to quickly locate the + group later (such as when implementing zones). The main advantage + of tagging as opposed to using Attributes is speed; a tag is very + limited in what data it can hold, and the tag key+category is + indexed for efficient lookup in the database. Tags are shared between + objects - a new tag is only created if the key+category combination + did not previously exist, making them unsuitable for storing + object-related data (for this a LiteAttribute or a full Attribute + should be used). + The 'db_data' field is intended as a documentation + field for the tag itself, such as to document what this tag+category + stands for and display that in a web interface or similar. + + The main default use for Tags is to implement Aliases for objects. + this uses the 'aliases' tag category, which is also checked by the + default search functions of Evennia to allow quick searches by alias. + """ + db_key = models.CharField('key', max_length=64, null=True, help_text="tag identifier") + db_category = models.CharField('category', max_length=32, null=True, help_text="tag category") + db_data = models.TextField('data', null=True, blank=True, help_text="optional data field with extra information. This is not searched for.") + + objects = managers.TagManager() + + class Meta: + "Define Django meta options" + verbose_name = "Tag" + unique_together = ('db_key', 'db_category') + index_together = ('db_key', 'db_category') + def __unicode__(self): + return u"%s" % self.db_key + def __str__(self): + return str(self.db_key) #------------------------------------------------------------ # @@ -417,9 +512,14 @@ class TypedObject(SharedMemoryModel): # Lock storage db_lock_storage = models.TextField('locks', blank=True, help_text="locks limit access to an entity. A lock is defined as a 'lock string' on the form 'type:lockfunctions', defining what functionality is locked and how to determine access. Not defining a lock means no access is granted.") - # attribute store. This is accessed through the self.db handler. + # many2many relationships db_attributes = models.ManyToManyField(Attribute, null=True, help_text='attributes on this object. An attribute can hold any pickle-able python object (see docs for special cases).') + db_liteattributes = models.ManyToManyField(LiteAttribute, null=True, + help_text='liteattributes on this object. A LiteAttribute holds a key, a category and a string field for simple lookups.') + db_tags = models.ManyToManyField(Tag, null=True, + help_text='tags on this object. Tags are simple string markers to identify, group and alias objects.') + # Database manager objects = managers.TypedObjectManager() @@ -1258,5 +1358,5 @@ class TypedObject(SharedMemoryModel): self.__class__.flush_cached_instance(self) -# connect to attribut cache signal +# connect to attribute cache signal m2m_changed.connect(post_attr_update, sender=TypedObject.db_attributes.through) From 2c17b7b675efb3343ceff5fd576d157b07a654e2 Mon Sep 17 00:00:00 2001 From: Griatch Date: Fri, 12 Jul 2013 12:04:57 +0200 Subject: [PATCH 27/49] Made the migrations for the new Tags and LiteAttributes. --- .../0022_add_db_liteattributes_db_tags.py | 141 +++++++++++++++ ...e_objectnick_db_nick_db_type_db_obj__de.py | 134 ++++++++++++++ src/objects/models.py | 98 +++++----- ...025_auto__add_db_liteattributes_db_tags.py | 117 ++++++++++++ ...nique_playernick_db_nick_db_type_db_obj.py | 105 +++++++++++ src/players/models.py | 54 +++--- ...dex_liteattribute_db_key_db_category__a.py | 81 +++++++++ ...copy_nicks_to_liteattrs_aliases_to_tags.py | 169 ++++++++++++++++++ src/typeclasses/models.py | 14 +- 9 files changed, 829 insertions(+), 84 deletions(-) create mode 100644 src/objects/migrations/0022_add_db_liteattributes_db_tags.py create mode 100644 src/objects/migrations/0023_auto__del_objectnick__del_unique_objectnick_db_nick_db_type_db_obj__de.py create mode 100644 src/players/migrations/0025_auto__add_db_liteattributes_db_tags.py create mode 100644 src/players/migrations/0026_auto__del_playernick__del_unique_playernick_db_nick_db_type_db_obj.py create mode 100644 src/typeclasses/migrations/0003_auto__add_liteattribute__add_index_liteattribute_db_key_db_category__a.py create mode 100644 src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py diff --git a/src/objects/migrations/0022_add_db_liteattributes_db_tags.py b/src/objects/migrations/0022_add_db_liteattributes_db_tags.py new file mode 100644 index 0000000000..9fcefb6a4a --- /dev/null +++ b/src/objects/migrations/0022_add_db_liteattributes_db_tags.py @@ -0,0 +1,141 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding M2M table for field db_liteattributes on 'ObjectDB' + m2m_table_name = db.shorten_name(u'objects_objectdb_db_liteattributes') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('objectdb', models.ForeignKey(orm[u'objects.objectdb'], null=False)), + ('liteattribute', models.ForeignKey(orm[u'typeclasses.liteattribute'], null=False)) + )) + db.create_unique(m2m_table_name, ['objectdb_id', 'liteattribute_id']) + + # Adding M2M table for field db_tags on 'ObjectDB' + m2m_table_name = db.shorten_name(u'objects_objectdb_db_tags') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('objectdb', models.ForeignKey(orm[u'objects.objectdb'], null=False)), + ('tag', models.ForeignKey(orm[u'typeclasses.tag'], null=False)) + )) + db.create_unique(m2m_table_name, ['objectdb_id', 'tag_id']) + + + def backwards(self, orm): + # Removing M2M table for field db_liteattributes on 'ObjectDB' + db.delete_table(db.shorten_name(u'objects_objectdb_db_liteattributes')) + + # Removing M2M table for field db_tags on 'ObjectDB' + db.delete_table(db.shorten_name(u'objects_objectdb_db_tags')) + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'objects.alias': { + 'Meta': {'object_name': 'Alias'}, + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['objects.ObjectDB']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'objects.objectdb': { + 'Meta': {'object_name': 'ObjectDB'}, + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destinations_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_home': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'homes_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_liteattributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.LiteAttribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_location': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locations_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']", 'null': 'True', 'blank': 'True'}), + 'db_sessid': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'db_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Tag']", 'null': 'True', 'symmetrical': 'False'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'objects.objectnick': { + 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'ObjectNick'}, + 'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['objects.ObjectDB']"}), + 'db_real': ('django.db.models.fields.TextField', [], {}), + 'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'players.playerdb': { + 'Meta': {'object_name': 'PlayerDB'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_liteattributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.LiteAttribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Tag']", 'null': 'True', 'symmetrical': 'False'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'typeclasses.attribute': { + 'Meta': {'object_name': 'Attribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.liteattribute': { + 'Meta': {'object_name': 'LiteAttribute', 'index_together': "(('db_key', 'db_category'),)"}, + 'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), + 'db_data': ('django.db.models.fields.TextField', [], {}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.tag': { + 'Meta': {'unique_together': "(('db_key', 'db_category'),)", 'object_name': 'Tag', 'index_together': "(('db_key', 'db_category'),)"}, + 'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}), + 'db_data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['objects'] diff --git a/src/objects/migrations/0023_auto__del_objectnick__del_unique_objectnick_db_nick_db_type_db_obj__de.py b/src/objects/migrations/0023_auto__del_objectnick__del_unique_objectnick_db_nick_db_type_db_obj__de.py new file mode 100644 index 0000000000..3f8ba80cab --- /dev/null +++ b/src/objects/migrations/0023_auto__del_objectnick__del_unique_objectnick_db_nick_db_type_db_obj__de.py @@ -0,0 +1,134 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + depends_on = (('typeclasses', '0004_copy_nicks_to_liteattrs_aliases_to_tags'),) + + def forwards(self, orm): + # Removing unique constraint on 'ObjectNick', fields ['db_nick', 'db_type', 'db_obj'] + db.delete_unique(u'objects_objectnick', ['db_nick', 'db_type', 'db_obj_id']) + + # Deleting model 'ObjectNick' + db.delete_table(u'objects_objectnick') + + # Deleting model 'Alias' + db.delete_table(u'objects_alias') + + + def backwards(self, orm): + # Adding model 'ObjectNick' + db.create_table(u'objects_objectnick', ( + ('db_type', self.gf('django.db.models.fields.CharField')(default='inputline', max_length=16, null=True, blank=True)), + ('db_nick', self.gf('django.db.models.fields.CharField')(max_length=255, db_index=True)), + ('db_obj', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['objects.ObjectDB'])), + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('db_real', self.gf('django.db.models.fields.TextField')()), + )) + db.send_create_signal(u'objects', ['ObjectNick']) + + # Adding unique constraint on 'ObjectNick', fields ['db_nick', 'db_type', 'db_obj'] + db.create_unique(u'objects_objectnick', ['db_nick', 'db_type', 'db_obj_id']) + + # Adding model 'Alias' + db.create_table(u'objects_alias', ( + ('db_obj', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['objects.ObjectDB'])), + ('db_key', self.gf('django.db.models.fields.CharField')(max_length=255, db_index=True)), + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + )) + db.send_create_signal(u'objects', ['Alias']) + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'objects.objectdb': { + 'Meta': {'object_name': 'ObjectDB'}, + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destinations_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_home': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'homes_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_liteattributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.LiteAttribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_location': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locations_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']", 'null': 'True', 'blank': 'True'}), + 'db_sessid': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'db_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Tag']", 'null': 'True', 'symmetrical': 'False'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'players.playerdb': { + 'Meta': {'object_name': 'PlayerDB'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_liteattributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.LiteAttribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Tag']", 'null': 'True', 'symmetrical': 'False'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'typeclasses.attribute': { + 'Meta': {'object_name': 'Attribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.liteattribute': { + 'Meta': {'object_name': 'LiteAttribute', 'index_together': "(('db_key', 'db_category'),)"}, + 'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), + 'db_data': ('django.db.models.fields.TextField', [], {}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.tag': { + 'Meta': {'unique_together': "(('db_key', 'db_category'),)", 'object_name': 'Tag', 'index_together': "(('db_key', 'db_category'),)"}, + 'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}), + 'db_data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['objects'] diff --git a/src/objects/models.py b/src/objects/models.py index b34ee43707..e502096c2a 100644 --- a/src/objects/models.py +++ b/src/objects/models.py @@ -24,7 +24,7 @@ from src.server.caches import get_field_cache, set_field_cache, del_field_cache from src.server.caches import get_prop_cache, set_prop_cache, del_prop_cache 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.players.models import PlayerDB from src.commands.cmdsethandler import CmdSetHandler @@ -54,55 +54,55 @@ _HERE = _("here") # #------------------------------------------------------------ -class Alias(SharedMemoryModel): - """ - This model holds a range of alternate names for an object. - These are intrinsic properties of the object. The split - is so as to allow for effective global searches also by - alias. - """ - db_key = models.CharField('alias', max_length=255, db_index=True) - db_obj = models.ForeignKey("ObjectDB", verbose_name='object') - - class Meta: - "Define Django meta options" - verbose_name = "Object alias" - verbose_name_plural = "Object aliases" - def __unicode__(self): - return u"%s" % self.db_key - def __str__(self): - return str(self.db_key) - - - -#------------------------------------------------------------ +#class Alias(SharedMemoryModel): +# """ +# This model holds a range of alternate names for an object. +# These are intrinsic properties of the object. The split +# is so as to allow for effective global searches also by +# alias. +# """ +# db_key = models.CharField('alias', max_length=255, db_index=True) +# db_obj = models.ForeignKey("ObjectDB", verbose_name='object') # -# Object Nicks +# class Meta: +# "Define Django meta options" +# verbose_name = "Object alias" +# verbose_name_plural = "Object aliases" +# def __unicode__(self): +# return u"%s" % self.db_key +# def __str__(self): +# return str(self.db_key) # -#------------------------------------------------------------ - -class ObjectNick(TypeNick): - """ - - The default nick types used by Evennia are: - inputline (default) - match against all input - player - match against player searches - obj - match against object searches - channel - used to store own names for channels - """ - db_obj = models.ForeignKey("ObjectDB", verbose_name='object') - - class Meta: - "Define Django meta options" - verbose_name = "Nickname for Objects" - verbose_name_plural = "Nicknames for Objects" - unique_together = ("db_nick", "db_type", "db_obj") - -class ObjectNickHandler(TypeNickHandler): - """ - Handles nick access and setting. Accessed through ObjectDB.nicks - """ - NickClass = ObjectNick +# +# +##------------------------------------------------------------ +## +## Object Nicks +## +##------------------------------------------------------------ +# +#class ObjectNick(TypeNick): +# """ +# +# The default nick types used by Evennia are: +# inputline (default) - match against all input +# player - match against player searches +# obj - match against object searches +# channel - used to store own names for channels +# """ +# db_obj = models.ForeignKey("ObjectDB", verbose_name='object') +# +# class Meta: +# "Define Django meta options" +# verbose_name = "Nickname for Objects" +# verbose_name_plural = "Nicknames for Objects" +# unique_together = ("db_nick", "db_type", "db_obj") +# +#class ObjectNickHandler(TypeNickHandler): +# """ +# Handles nick access and setting. Accessed through ObjectDB.nicks +# """ +# NickClass = ObjectNick #------------------------------------------------------------ @@ -199,7 +199,7 @@ class ObjectDB(TypedObject): _SA(self, "cmdset", CmdSetHandler(self)) _GA(self, "cmdset").update(init_mode=True) _SA(self, "scripts", ScriptHandler(self)) - _SA(self, "nicks", ObjectNickHandler(self)) + #_SA(self, "nicks", ObjectNickHandler(self)) # Wrapper properties to easily set database fields. These are # @property decorators that allows to access these fields using diff --git a/src/players/migrations/0025_auto__add_db_liteattributes_db_tags.py b/src/players/migrations/0025_auto__add_db_liteattributes_db_tags.py new file mode 100644 index 0000000000..ad62bb2288 --- /dev/null +++ b/src/players/migrations/0025_auto__add_db_liteattributes_db_tags.py @@ -0,0 +1,117 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding M2M table for field db_liteattributes on 'PlayerDB' + m2m_table_name = db.shorten_name(u'players_playerdb_db_liteattributes') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('playerdb', models.ForeignKey(orm[u'players.playerdb'], null=False)), + ('liteattribute', models.ForeignKey(orm[u'typeclasses.liteattribute'], null=False)) + )) + db.create_unique(m2m_table_name, ['playerdb_id', 'liteattribute_id']) + + # Adding M2M table for field db_tags on 'PlayerDB' + m2m_table_name = db.shorten_name(u'players_playerdb_db_tags') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('playerdb', models.ForeignKey(orm[u'players.playerdb'], null=False)), + ('tag', models.ForeignKey(orm[u'typeclasses.tag'], null=False)) + )) + db.create_unique(m2m_table_name, ['playerdb_id', 'tag_id']) + + + def backwards(self, orm): + # Removing M2M table for field db_liteattributes on 'PlayerDB' + db.delete_table(db.shorten_name(u'players_playerdb_db_liteattributes')) + + # Removing M2M table for field db_tags on 'PlayerDB' + db.delete_table(db.shorten_name(u'players_playerdb_db_tags')) + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'players.playerdb': { + 'Meta': {'object_name': 'PlayerDB'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_liteattributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.LiteAttribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Tag']", 'null': 'True', 'symmetrical': 'False'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'players.playernick': { + 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, + 'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}), + 'db_real': ('django.db.models.fields.TextField', [], {}), + 'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.attribute': { + 'Meta': {'object_name': 'Attribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.liteattribute': { + 'Meta': {'object_name': 'LiteAttribute', 'index_together': "(('db_key', 'db_category'),)"}, + 'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), + 'db_data': ('django.db.models.fields.TextField', [], {}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.tag': { + 'Meta': {'unique_together': "(('db_key', 'db_category'),)", 'object_name': 'Tag', 'index_together': "(('db_key', 'db_category'),)"}, + 'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}), + 'db_data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['players'] diff --git a/src/players/migrations/0026_auto__del_playernick__del_unique_playernick_db_nick_db_type_db_obj.py b/src/players/migrations/0026_auto__del_playernick__del_unique_playernick_db_nick_db_type_db_obj.py new file mode 100644 index 0000000000..f2b4a85b6c --- /dev/null +++ b/src/players/migrations/0026_auto__del_playernick__del_unique_playernick_db_nick_db_type_db_obj.py @@ -0,0 +1,105 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + depends_on = (('typeclasses', '0004_copy_nicks_to_liteattrs_aliases_to_tags'),) + + def forwards(self, orm): + # Removing unique constraint on 'PlayerNick', fields ['db_nick', 'db_type', 'db_obj'] + db.delete_unique(u'players_playernick', ['db_nick', 'db_type', 'db_obj_id']) + + # Deleting model 'PlayerNick' + db.delete_table(u'players_playernick') + + + def backwards(self, orm): + # Adding model 'PlayerNick' + db.create_table(u'players_playernick', ( + ('db_type', self.gf('django.db.models.fields.CharField')(default='inputline', max_length=16, null=True, blank=True)), + ('db_nick', self.gf('django.db.models.fields.CharField')(max_length=255, db_index=True)), + ('db_obj', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['players.PlayerDB'])), + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('db_real', self.gf('django.db.models.fields.TextField')()), + )) + db.send_create_signal(u'players', ['PlayerNick']) + + # Adding unique constraint on 'PlayerNick', fields ['db_nick', 'db_type', 'db_obj'] + db.create_unique(u'players_playernick', ['db_nick', 'db_type', 'db_obj_id']) + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'players.playerdb': { + 'Meta': {'object_name': 'PlayerDB'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_liteattributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.LiteAttribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Tag']", 'null': 'True', 'symmetrical': 'False'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'typeclasses.attribute': { + 'Meta': {'object_name': 'Attribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.liteattribute': { + 'Meta': {'object_name': 'LiteAttribute', 'index_together': "(('db_key', 'db_category'),)"}, + 'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), + 'db_data': ('django.db.models.fields.TextField', [], {}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.tag': { + 'Meta': {'unique_together': "(('db_key', 'db_category'),)", 'object_name': 'Tag', 'index_together': "(('db_key', 'db_category'),)"}, + 'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}), + 'db_data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['players'] diff --git a/src/players/models.py b/src/players/models.py index ca10ebb574..ee42972d66 100644 --- a/src/players/models.py +++ b/src/players/models.py @@ -59,34 +59,34 @@ _DA = object.__delattr__ _TYPECLASS = None -#------------------------------------------------------------ +##------------------------------------------------------------ +## +## Player Nicks +## +##------------------------------------------------------------ # -# Player Nicks +#class PlayerNick(TypeNick): +# """ # -#------------------------------------------------------------ - -class PlayerNick(TypeNick): - """ - - The default nick types used by Evennia are: - inputline (default) - match against all input - player - match against player searches - obj - match against object searches - channel - used to store own names for channels - """ - db_obj = models.ForeignKey("PlayerDB", verbose_name="player") - - class Meta: - "Define Django meta options" - verbose_name = "Nickname for Players" - verbose_name_plural = "Nicknames Players" - unique_together = ("db_nick", "db_type", "db_obj") - -class PlayerNickHandler(TypeNickHandler): - """ - Handles nick access and setting. Accessed through ObjectDB.nicks - """ - NickClass = PlayerNick +# The default nick types used by Evennia are: +# inputline (default) - match against all input +# player - match against player searches +# obj - match against object searches +# channel - used to store own names for channels +# """ +# db_obj = models.ForeignKey("PlayerDB", verbose_name="player") +# +# class Meta: +# "Define Django meta options" +# verbose_name = "Nickname for Players" +# verbose_name_plural = "Nicknames Players" +# unique_together = ("db_nick", "db_type", "db_obj") +# +#class PlayerNickHandler(TypeNickHandler): +# """ +# Handles nick access and setting. Accessed through ObjectDB.nicks +# """ +# NickClass = PlayerNick #------------------------------------------------------------ @@ -153,7 +153,7 @@ class PlayerDB(TypedObject, AbstractUser): # handlers _SA(self, "cmdset", CmdSetHandler(self)) _GA(self, "cmdset").update(init_mode=True) - _SA(self, "nicks", PlayerNickHandler(self)) + #_SA(self, "nicks", PlayerNickHandler(self)) # Wrapper properties to easily set database fields. These are # @property decorators that allows to access these fields using diff --git a/src/typeclasses/migrations/0003_auto__add_liteattribute__add_index_liteattribute_db_key_db_category__a.py b/src/typeclasses/migrations/0003_auto__add_liteattribute__add_index_liteattribute_db_key_db_category__a.py new file mode 100644 index 0000000000..01a4f29685 --- /dev/null +++ b/src/typeclasses/migrations/0003_auto__add_liteattribute__add_index_liteattribute_db_key_db_category__a.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'LiteAttribute' + db.create_table(u'typeclasses_liteattribute', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('db_key', self.gf('django.db.models.fields.CharField')(max_length=255)), + ('db_category', self.gf('django.db.models.fields.CharField')(max_length=64, null=True, blank=True)), + ('db_data', self.gf('django.db.models.fields.TextField')()), + )) + db.send_create_signal(u'typeclasses', ['LiteAttribute']) + + # Adding index on 'LiteAttribute', fields ['db_key', 'db_category'] + db.create_index(u'typeclasses_liteattribute', ['db_key', 'db_category']) + + # Adding model 'Tag' + db.create_table(u'typeclasses_tag', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('db_key', self.gf('django.db.models.fields.CharField')(max_length=255, null=True)), + ('db_category', self.gf('django.db.models.fields.CharField')(max_length=64, null=True)), + ('db_data', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), + )) + db.send_create_signal(u'typeclasses', ['Tag']) + + # Adding unique constraint on 'Tag', fields ['db_key', 'db_category'] + db.create_unique(u'typeclasses_tag', ['db_key', 'db_category']) + + # Adding index on 'Tag', fields ['db_key', 'db_category'] + db.create_index(u'typeclasses_tag', ['db_key', 'db_category']) + + + def backwards(self, orm): + # Removing index on 'Tag', fields ['db_key', 'db_category'] + db.delete_index(u'typeclasses_tag', ['db_key', 'db_category']) + + # Removing unique constraint on 'Tag', fields ['db_key', 'db_category'] + db.delete_unique(u'typeclasses_tag', ['db_key', 'db_category']) + + # Removing index on 'LiteAttribute', fields ['db_key', 'db_category'] + db.delete_index(u'typeclasses_liteattribute', ['db_key', 'db_category']) + + # Deleting model 'LiteAttribute' + db.delete_table(u'typeclasses_liteattribute') + + # Deleting model 'Tag' + db.delete_table(u'typeclasses_tag') + + + models = { + u'typeclasses.attribute': { + 'Meta': {'object_name': 'Attribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.liteattribute': { + 'Meta': {'object_name': 'LiteAttribute', 'index_together': "(('db_key', 'db_category'),)"}, + 'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), + 'db_data': ('django.db.models.fields.TextField', [], {}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.tag': { + 'Meta': {'unique_together': "(('db_key', 'db_category'),)", 'object_name': 'Tag', 'index_together': "(('db_key', 'db_category'),)"}, + 'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}), + 'db_data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['typeclasses'] \ No newline at end of file diff --git a/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py b/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py new file mode 100644 index 0000000000..09f3eccaec --- /dev/null +++ b/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py @@ -0,0 +1,169 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import DataMigration +from django.db import models + +class Migration(DataMigration): + + depends_on = (("objects", "0022_add_db_liteattributes_db_tags"), + ("players", "0025_auto__add_db_liteattributes_db_tags")) + def forwards(self, orm): + "Write your forwards methods here." + # Note: Don't use "from appname.models import ModelName". + # Use orm.ModelName to refer to models in this application, + # and orm['appname.ModelName'] for models in other applications. + for alias in orm['objects.Alias'].objects.all(): + # convert all Aliases to tags + tag = orm.Tag(db_key=alias.db_key, db_category="aliases", db_data=None) + tag.save() + obj = alias.db_obj + obj.db_tags.add(tag) + # convert all nicks to LiteAttrs + for nick in orm['objects.ObjectNick'].objects.all(): + lattr = orm.LiteAttribute(db_key=nick.db_nick, db_category="nick_%s" % nick.db_type, db_data=nick.db_real) + lattr.save() + obj = nick.db_obj + obj.db_liteattributes.add(lattr) + for nick in orm['players.PlayerNick'].objects.all(): + lattr = orm.LiteAttribute(db_key=nick.db_nick, db_category="nick_%s" % nick.db_type, db_data=nick.db_real) + lattr.save() + obj = nick.db_obj + obj.db_liteattributes.add(lattr) + + + def backwards(self, orm): + "Write your backwards methods here." + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'objects.alias': { + 'Meta': {'object_name': 'Alias'}, + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['objects.ObjectDB']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'objects.objectdb': { + 'Meta': {'object_name': 'ObjectDB'}, + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destinations_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_home': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'homes_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_liteattributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.LiteAttribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_location': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locations_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']", 'null': 'True', 'blank': 'True'}), + 'db_sessid': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'db_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Tag']", 'null': 'True', 'symmetrical': 'False'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'objects.objectnick': { + 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'ObjectNick'}, + 'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['objects.ObjectDB']"}), + 'db_real': ('django.db.models.fields.TextField', [], {}), + 'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'players.playerdb': { + 'Meta': {'object_name': 'PlayerDB'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_liteattributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.LiteAttribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Tag']", 'null': 'True', 'symmetrical': 'False'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'players.playernick': { + 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, + 'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']"}), + 'db_real': ('django.db.models.fields.TextField', [], {}), + 'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'scripts.scriptdb': { + 'Meta': {'object_name': 'ScriptDB'}, + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_desc': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_interval': ('django.db.models.fields.IntegerField', [], {'default': '-1'}), + 'db_is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_liteattributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.LiteAttribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['objects.ObjectDB']", 'null': 'True', 'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_persistent': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_repeats': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'db_start_delay': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Tag']", 'null': 'True', 'symmetrical': 'False'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.attribute': { + 'Meta': {'object_name': 'Attribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.liteattribute': { + 'Meta': {'object_name': 'LiteAttribute', 'index_together': "(('db_key', 'db_category'),)"}, + 'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), + 'db_data': ('django.db.models.fields.TextField', [], {}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.tag': { + 'Meta': {'unique_together': "(('db_key', 'db_category'),)", 'object_name': 'Tag', 'index_together': "(('db_key', 'db_category'),)"}, + 'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}), + 'db_data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['objects', 'scripts', 'players', 'typeclasses'] + symmetrical = True diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index 26f929aae9..c7d0699b79 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -290,16 +290,15 @@ class LiteAttribute(models.Model): """ db_key = models.CharField('key', max_length=255, help_text='name if liteattribute') - db_category = models.CharField('category', max_length=32, null=True, blank=True, help_text="liteattribute category") + db_category = models.CharField('category', max_length=64, null=True, blank=True, help_text="liteattribute category") db_data = models.TextField('data', help_text='holds string data') objects = managers.LiteAttributeManager() class Meta: "Define Django meta options" - abstract = True verbose_name = "Lite Attribute" - index_together = ("db_key", "db_category") + index_together = (("db_key", "db_category"),) def __unicode__(self): return u"%s" % self.db_key def __str__(self): @@ -332,17 +331,16 @@ class Tag(models.Model): this uses the 'aliases' tag category, which is also checked by the default search functions of Evennia to allow quick searches by alias. """ - db_key = models.CharField('key', max_length=64, null=True, help_text="tag identifier") - db_category = models.CharField('category', max_length=32, null=True, help_text="tag category") + db_key = models.CharField('key', max_length=255, null=True, help_text="tag identifier") + db_category = models.CharField('category', max_length=64, null=True, help_text="tag category") db_data = models.TextField('data', null=True, blank=True, help_text="optional data field with extra information. This is not searched for.") objects = managers.TagManager() - class Meta: "Define Django meta options" verbose_name = "Tag" - unique_together = ('db_key', 'db_category') - index_together = ('db_key', 'db_category') + unique_together =(('db_key', 'db_category'),) + index_together = (('db_key', 'db_category'),) def __unicode__(self): return u"%s" % self.db_key def __str__(self): From 0061f884ae628bbd571930d23b0e566bee6788bc Mon Sep 17 00:00:00 2001 From: Griatch Date: Fri, 12 Jul 2013 14:44:49 +0200 Subject: [PATCH 28/49] Implemented NickHandler, AliasHandler and TagHandler in the typeclass to replace the old handlers. Some errors during login. --- src/commands/default/comms.py | 2 +- src/objects/models.py | 112 ++-------- src/players/models.py | 56 ++--- src/scripts/models.py | 8 +- src/typeclasses/managers.py | 13 +- ...copy_nicks_to_liteattrs_aliases_to_tags.py | 6 +- src/typeclasses/models.py | 201 +++++++++++------- 7 files changed, 176 insertions(+), 222 deletions(-) diff --git a/src/commands/default/comms.py b/src/commands/default/comms.py index b886306c41..4bee66e81e 100644 --- a/src/commands/default/comms.py +++ b/src/commands/default/comms.py @@ -160,7 +160,7 @@ class CmdDelCom(MuxPlayerCommand): if not channel: self.msg("No channel with alias '%s' was found." % ostring) else: - if caller.nicks.has(ostring, nick_type="channel"): + if caller.nicks.get(ostring, nick_type="channel", default=False): caller.nicks.delete(ostring, nick_type="channel") self.msg("Your alias '%s' for channel %s was cleared." % (ostring, channel.key)) else: diff --git a/src/objects/models.py b/src/objects/models.py index e502096c2a..c7dccb7855 100644 --- a/src/objects/models.py +++ b/src/objects/models.py @@ -18,13 +18,11 @@ import traceback from django.db import models from django.conf import settings -from src.utils.idmapper.models import SharedMemoryModel -from src.typeclasses.models import Attribute, TypedObject, TypeNick, TypeNickHandler +from src.typeclasses.models import TypedObject, TagHandler, NickHandler, AliasHandler from src.server.caches import get_field_cache, set_field_cache, del_field_cache -from src.server.caches import get_prop_cache, set_prop_cache, del_prop_cache +from src.server.caches import get_prop_cache, set_prop_cache from src.typeclasses.typeclass import TypeClass -#from src.players.models import PlayerNick from src.objects.manager import ObjectManager from src.players.models import PlayerDB from src.commands.cmdsethandler import CmdSetHandler @@ -35,7 +33,7 @@ from src.utils.utils import make_iter, to_unicode, variable_from_module, inherit from django.utils.translation import ugettext as _ -#__all__ = ("Alias", "ObjectNick", "ObjectDB") +#__all__ = ("ObjectDB", ) _ScriptDB = None _AT_SEARCH_RESULT = variable_from_module(*settings.SEARCH_AT_RESULT.rsplit('.', 1)) @@ -48,63 +46,6 @@ _ME = _("me") _SELF = _("self") _HERE = _("here") -#------------------------------------------------------------ -# -# Alias -# -#------------------------------------------------------------ - -#class Alias(SharedMemoryModel): -# """ -# This model holds a range of alternate names for an object. -# These are intrinsic properties of the object. The split -# is so as to allow for effective global searches also by -# alias. -# """ -# db_key = models.CharField('alias', max_length=255, db_index=True) -# db_obj = models.ForeignKey("ObjectDB", verbose_name='object') -# -# class Meta: -# "Define Django meta options" -# verbose_name = "Object alias" -# verbose_name_plural = "Object aliases" -# def __unicode__(self): -# return u"%s" % self.db_key -# def __str__(self): -# return str(self.db_key) -# -# -# -##------------------------------------------------------------ -## -## Object Nicks -## -##------------------------------------------------------------ -# -#class ObjectNick(TypeNick): -# """ -# -# The default nick types used by Evennia are: -# inputline (default) - match against all input -# player - match against player searches -# obj - match against object searches -# channel - used to store own names for channels -# """ -# db_obj = models.ForeignKey("ObjectDB", verbose_name='object') -# -# class Meta: -# "Define Django meta options" -# verbose_name = "Nickname for Objects" -# verbose_name_plural = "Nicknames for Objects" -# unique_together = ("db_nick", "db_type", "db_obj") -# -#class ObjectNickHandler(TypeNickHandler): -# """ -# Handles nick access and setting. Accessed through ObjectDB.nicks -# """ -# NickClass = ObjectNick - - #------------------------------------------------------------ # # ObjectDB @@ -199,7 +140,9 @@ class ObjectDB(TypedObject): _SA(self, "cmdset", CmdSetHandler(self)) _GA(self, "cmdset").update(init_mode=True) _SA(self, "scripts", ScriptHandler(self)) - #_SA(self, "nicks", ObjectNickHandler(self)) + _SA(self, "tags", TagHandler(self, "object")) + _SA(self, "aliases", AliasHandler(self, "object")) + _SA(self, "nicks", NickHandler(self, "object")) # Wrapper properties to easily set database fields. These are # @property decorators that allows to access these fields using @@ -209,30 +152,6 @@ class ObjectDB(TypedObject): # value = self.attr and del self.attr respectively (where self # is the object in question). - # aliases property (wraps (db_aliases) - #@property - def __aliases_get(self): - "Getter. Allows for value = self.aliases" - aliases = get_prop_cache(self, "_aliases") - if aliases == None: - aliases = list(Alias.objects.filter(db_obj=self).values_list("db_key", flat=True)) - set_prop_cache(self, "_aliases", aliases) - return aliases - #@aliases.setter - def __aliases_set(self, aliases): - "Setter. Allows for self.aliases = value" - for alias in make_iter(aliases): - new_alias = Alias(db_key=alias, db_obj=self) - new_alias.save() - set_prop_cache(self, "_aliases", make_iter(aliases)) - #@aliases.deleter - def __aliases_del(self): - "Deleter. Allows for del self.aliases" - for alias in Alias.objects.filter(db_obj=self): - alias.delete() - #del_prop_cache(self, "_aliases") - aliases = property(__aliases_get, __aliases_set, __aliases_del) - # player property (wraps db_player) #@property def __player_get(self): @@ -643,12 +562,12 @@ class ObjectDB(TypedObject): return self.typeclass if use_nicks: - nick = None nicktype = "object" - # look up nicks - nicks = ObjectNick.objects.filter(db_obj=self, db_type=nicktype) + # get all valid nicks to search + nicks = self.nicks.get(category="object_nick_%s" % nicktype) if self.has_player: - nicks = list(nicks) + list(PlayerNick.objects.filter(db_obj=self.db_player, db_type=nicktype)) + pnicks = self.nicks.get(category="player_nick_%s" % nicktype) + nicks = nicks + pnicks for nick in nicks: if searchdata == nick.db_nick: searchdata = nick.db_real @@ -723,12 +642,15 @@ class ObjectDB(TypedObject): raw_list = raw_string.split(None) raw_list = [" ".join(raw_list[:i+1]) for i in range(len(raw_list)) if raw_list[:i+1]] - nicks = ObjectNick.objects.filter(db_obj=self, db_type__in=("inputline", "channel")) + # fetch the nick data efficiently + nicks = self.db_lnattributes.filter(db_category__in=("object_nick_inputline", "object_nick_channel")).prefetch_related("db_key","db_data") if self.has_player: - nicks = list(nicks) + list(PlayerNick.objects.filter(db_obj=self.db_player, db_type__in=("inputline","channel"))) + pnicks = self.player.db_lnattributes.filter( + db_category__in=("player_nick_inputline", "player_nick_channel")).prefetch_related("db_key","db_data") + nicks = nicks + pnicks for nick in nicks: - if nick.db_nick in raw_list: - raw_string = raw_string.replace(nick.db_nick, nick.db_real, 1) + if nick.db_key in raw_list: + raw_string = raw_string.replace(nick.db_key, nick.db_data, 1) break return cmdhandler.cmdhandler(_GA(self, "typeclass"), raw_string, sessid=sessid) diff --git a/src/players/models.py b/src/players/models.py index ee42972d66..af7d0f7f65 100644 --- a/src/players/models.py +++ b/src/players/models.py @@ -25,25 +25,21 @@ account info and OOC account configuration variables etc. from django.conf import settings from django.db import models -from django.contrib.auth.models import AbstractUser, User +from django.contrib.auth.models import AbstractUser from django.utils.encoding import smart_str -from django.db.models.signals import post_init, pre_delete -from src.server.caches import get_field_cache, set_field_cache, del_field_cache -from src.server.caches import get_prop_cache, set_prop_cache, del_prop_cache +from src.server.caches import get_field_cache, set_field_cache from src.players import manager from src.scripts.models import ScriptDB -from src.typeclasses.models import Attribute, TypedObject, TypeNick, TypeNickHandler -from src.typeclasses.typeclass import TypeClass +from src.typeclasses.models import TypedObject, TagHandler, NickHandler, AliasHandler from src.commands.cmdsethandler import CmdSetHandler from src.commands import cmdhandler -from src.utils import logger, utils -from src.utils.utils import inherits_from, make_iter +from src.utils import utils from django.utils.translation import ugettext as _ -__all__ = ("PlayerNick", "PlayerDB") +__all__ = ("PlayerDB",) _ME = _("me") _SELF = _("self") @@ -59,35 +55,6 @@ _DA = object.__delattr__ _TYPECLASS = None -##------------------------------------------------------------ -## -## Player Nicks -## -##------------------------------------------------------------ -# -#class PlayerNick(TypeNick): -# """ -# -# The default nick types used by Evennia are: -# inputline (default) - match against all input -# player - match against player searches -# obj - match against object searches -# channel - used to store own names for channels -# """ -# db_obj = models.ForeignKey("PlayerDB", verbose_name="player") -# -# class Meta: -# "Define Django meta options" -# verbose_name = "Nickname for Players" -# verbose_name_plural = "Nicknames Players" -# unique_together = ("db_nick", "db_type", "db_obj") -# -#class PlayerNickHandler(TypeNickHandler): -# """ -# Handles nick access and setting. Accessed through ObjectDB.nicks -# """ -# NickClass = PlayerNick - #------------------------------------------------------------ # @@ -153,7 +120,9 @@ class PlayerDB(TypedObject, AbstractUser): # handlers _SA(self, "cmdset", CmdSetHandler(self)) _GA(self, "cmdset").update(init_mode=True) - #_SA(self, "nicks", PlayerNickHandler(self)) + _SA(self, "tags", TagHandler(self, "player")) + _SA(self, "aliases", AliasHandler(self, "player")) + _SA(self, "nicks", NickHandler(self, "player")) # Wrapper properties to easily set database fields. These are # @property decorators that allows to access these fields using @@ -520,9 +489,12 @@ class PlayerDB(TypedObject, AbstractUser): raw_list = raw_string.split(None) raw_list = [" ".join(raw_list[:i+1]) for i in range(len(raw_list)) if raw_list[:i+1]] - for nick in PlayerNick.objects.filter(db_obj=self, db_type__in=("inputline","channel")): - if nick.db_nick in raw_list: - raw_string = raw_string.replace(nick.db_nick, nick.db_real, 1) + # get the nick replacement data directly from the database to be able to use db_category__in + nicks = self.db_liteattributes.filter( + db_category__in=("object_nick_inputline", "object_nick_channel")).prefetch_related("db_key","db_data") + for nick in nicks: + if nick.db_key in raw_list: + raw_string = raw_string.replace(nick.db_key, nick.db_data, 1) break if not sessid and _MULTISESSION_MODE in (0, 1): # in this case, we should either have only one sessid, or the sessid diff --git a/src/scripts/models.py b/src/scripts/models.py index cc29d96580..9b47b3d0b4 100644 --- a/src/scripts/models.py +++ b/src/scripts/models.py @@ -28,7 +28,7 @@ from django.conf import settings from django.db import models from django.db.models.signals import post_init, pre_delete -from src.typeclasses.models import Attribute, TypedObject +from src.typeclasses.models import Attribute, TypedObject, TagHandler, AliasHandler, NickHandler from django.contrib.contenttypes.models import ContentType from src.scripts.manager import ScriptManager @@ -104,6 +104,12 @@ class ScriptDB(TypedObject): "Define Django meta options" verbose_name = "Script" + def __init__(self, *args, **kwargs): + super(ScriptDB, self).__init__(self, *args, **kwargs) + _SA(self, "tags", TagHandler(self, "script")) + _SA(self, "aliases", AliasHandler(self, "script")) + + # 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() diff --git a/src/typeclasses/managers.py b/src/typeclasses/managers.py index 0ee0f0a21c..ae84ce2389 100644 --- a/src/typeclasses/managers.py +++ b/src/typeclasses/managers.py @@ -101,9 +101,9 @@ class LiteAttributeManager(models.Manager): if search_key or category: key_cands = Q(db_key__iexact=search_key.lower().strip()) if search_key!=None else Q() cat_cands = Q(db_category__iexact=category.lower.strip()) if search_key!=None else Q() - return _GA(obj, "db_tags").filter(cat_cands & key_cands) + return _GA(obj, "db_liteattributes").filter(cat_cands & key_cands) else: - return list(_GA(obj, "db_tags").all()) + return list(_GA(obj, "db_liteattributes").all()) def get_lattr(self, search_key=None, category=None): """ @@ -167,10 +167,17 @@ class TagManager(models.Manager): the search criteria. search_key (string) - the tag identifier category (string) - the tag category + + Returns a single Tag (or None) if both key and category is given, otherwise + it will return a list. """ key_cands = Q(db_key__iexact=search_key.lower().strip()) if search_key!=None else Q() cat_cands = Q(db_category__iexact=category.lower.strip()) if search_key!=None else Q() - return list(self.filter(key_cands & cat_cands)) + tags = self.filter(key_cands & cat_cands) + if search_key and category: + return tags[0] if tags else None + else: + return list(tags) def get_objs_with_tag(self, objclass, search_key=None, category=None): """ diff --git a/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py b/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py index 09f3eccaec..f133b43d32 100644 --- a/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py +++ b/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py @@ -15,18 +15,18 @@ class Migration(DataMigration): # and orm['appname.ModelName'] for models in other applications. for alias in orm['objects.Alias'].objects.all(): # convert all Aliases to tags - tag = orm.Tag(db_key=alias.db_key, db_category="aliases", db_data=None) + tag = orm.Tag(db_key=alias.db_key, db_category="object_alias", db_data=None) tag.save() obj = alias.db_obj obj.db_tags.add(tag) # convert all nicks to LiteAttrs for nick in orm['objects.ObjectNick'].objects.all(): - lattr = orm.LiteAttribute(db_key=nick.db_nick, db_category="nick_%s" % nick.db_type, db_data=nick.db_real) + lattr = orm.LiteAttribute(db_key=nick.db_nick, db_category="object_nick_%s" % nick.db_type, db_data=nick.db_real) lattr.save() obj = nick.db_obj obj.db_liteattributes.add(lattr) for nick in orm['players.PlayerNick'].objects.all(): - lattr = orm.LiteAttribute(db_key=nick.db_nick, db_category="nick_%s" % nick.db_type, db_data=nick.db_real) + lattr = orm.LiteAttribute(db_key=nick.db_nick, db_category="player_nick_%s" % nick.db_type, db_data=nick.db_real) lattr.save() obj = nick.db_obj obj.db_liteattributes.add(lattr) diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index c7d0699b79..fe3e992eba 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -346,52 +346,104 @@ class Tag(models.Model): def __str__(self): return str(self.db_key) -#------------------------------------------------------------ + # -# Nicks +# Helper handlers # -#------------------------------------------------------------ -class TypeNick(SharedMemoryModel): +class TagHandler(object): """ - This model holds whichever alternate names this object - has for OTHER objects, but also for arbitrary strings, - channels, players etc. Setting a nick does not affect - the nicknamed object at all (as opposed to Aliases above), - and only this object will be able to refer to the nicknamed - object by the given nick. - - The default nick types used by Evennia are: - inputline (default) - match against all input - player - match against player searches - obj - match against object searches - channel - used to store own names for channels - + Generic tag-handler. Accessed via TypedObject.tags. """ - db_nick = models.CharField('nickname',max_length=255, db_index=True, help_text='the alias') - db_real = models.TextField('realname', help_text='the original string to match and replace.') - db_type = models.CharField('nick type',default="inputline", max_length=16, null=True, blank=True, - help_text="the nick type describes when the engine tries to do nick-replacement. Common options are 'inputline','player','obj' and 'channel'. Inputline checks everything being inserted, whereas the other cases tries to replace in various searches or when posting to channels.") - db_obj = None #models.ForeignKey("ObjectDB") - - class Meta: - "Define Django meta options" - abstract = True - verbose_name = "Nickname" - unique_together = ("db_nick", "db_type", "db_obj") - -class TypeNickHandler(object): - """ - Handles nick access and setting. Accessed through ObjectDB.nicks - """ - - NickClass = TypeNick - - def __init__(self, obj): + def __init__(self, obj, category_prefix=""): """ - This handler allows for accessing and setting nicks - - on-the-fly replacements for various text input passing through - this object (most often a Character) + Tags are stored internally in the TypedObject.db_tags m2m field + using the category + """ + self.obj = obj + self.prefix = category_prefix.strip().lower() if category_prefix else "" + + def add(self, tag, category=None, data=None): + "Add a new tag to the handler" + tag = tag.strip().lower() if tag!=None else None + category = "%s%s" % (self.prefix, category.strip.lower()) if category!=None else None + data = str(data) if data!=None else None + # this will only create tag if no matches existed beforehand (it will overload + # data on an existing tag since that is not considered part of making the tag unique) + tagobj = Tag.objects.create_tag(key=tag, category=category, data=data) + self.obj.db_tags.add(tagobj) + + def remove(self, tag, category=None): + "Remove a tag from the handler" + tag = tag.strip().lower() if tag!=None else None + category = "%s%s" % (self.prefix, category.strip.lower()) if category!=None else None + #TODO This does not delete the tag object itself. Maybe it should do that when no + # objects reference the tag anymore? + tagobj = self.obj.db_tags.filter(db_key=tag, db_category=category) + if tagobj: + self.obj.remove(tagobj[0]) + + def all(self): + "Get all tags in this handler" + return self.obj.db_tags.all().get_values("db_key") + + def __str__(self): + return ",".join(self.all()) + def __unicode(self): + return u",".join(self.all()) + + + +class AliasHandler(object): + """ + Handles alias access and setting. Accessed through TypedObject.aliases. + """ + def __init__(self, obj, category_prefix="object_"): + """ + Aliases are alternate names for an entity. + Implements the alias handler, using Tags for storage and + the _alias tag category. It is available + as TypedObjects.aliases. + """ + self.obj = obj + self.category = "%salias" % category_prefix + + def add(self, alias): + "Add a new nick to the handler" + if not alias or not alias.strip(): + return + alias = alias.strip() + # create a unique tag only if it didn't already exist + aliasobj = Tag.objects.create_tag(key=alias, category=self.category) + self.obj.db_tags.add(aliasobj) + + def remove(self, alias): + "Remove alias from handler." + aliasobj = Tag.objects.filter(db_key__iexact=alias.strip(), category=self.category).count() + #TODO note that this doesn't delete the tag itself. We might want to do this when no object + # uses it anymore ... + self.obj.db_tags.remove(aliasobj) + + def all(self): + "Get all aliases in this handler" + return self.obj.db_tags.filter(db_category=self.category).get_values("db_key") + + def __str__(self): + return ",".join(self.all()) + def __unicode(self): + return u",".join(self.all()) + + +class NickHandler(object): + """ + Handles nick access and setting. Accessed through TypedObject.nicks. + """ + + def __init__(self, obj, category_prefix="object_"): + """ + Nicks are alternate names an entity as of ANOTHER entity. The + engine will auto-replace nicks under circumstances dictated + by the nick category. It uses LiteAttributes for storage. The default nick types used by Evennia are: @@ -400,13 +452,11 @@ class TypeNickHandler(object): obj - match against object searches channel - used to store own names for channels - You can define other nicktypes by using the add() method of - this handler and set nick_type to whatever you want. It's then - up to you to somehow make use of this nick_type in your game - (such as for a "recog" system). - + These are all stored interally using categories + nick_inputline etc. """ self.obj = obj + self.prefix = "%snick_" % category_prefix.strip().lower() if category_prefix else "" def add(self, nick, realname, nick_type="inputline"): """ @@ -417,50 +467,47 @@ class TypeNickHandler(object): if not nick or not nick.strip(): return nick = nick.strip() - real = realname.strip() - query = self.NickClass.objects.filter(db_obj=self.obj, db_nick__iexact=nick, db_type__iexact=nick_type) + real = realname + nick_type = "%s%s" % (self.prefix, nick_type.strip().lower()) + query = self.obj.db_liteattributes.filter(db_key__iexact=nick, db_category__iexact=nick_type) if query.count(): old_nick = query[0] - old_nick.db_real = real + old_nick.db_data = real old_nick.save() else: - new_nick = self.NickClass(db_nick=nick, db_real=real, db_type=nick_type, db_obj=self.obj) + new_nick = LiteAttribute(db_key=nick, db_category=nick_type, db_data=real) new_nick.save() - def delete(self, nick, nick_type="inputline"): + self.obj.db_liteattributes.add(new_nick) + + def remove(self, nick, nick_type="inputline"): "Removes a previously stored nick" nick = nick.strip() - query = self.NickClass.objects.filter(db_obj=self.obj, db_nick__iexact=nick, db_type__iexact=nick_type) + nick_type = "%s%s" % (self.prefix, nick_type.strip().lower()) + query = self.obj.liteattributes.filter(db_key__iexact=nick, db_category__iexact=nick_type) if query.count(): # remove the found nick(s) query.delete() - def get(self, nick=None, nick_type="inputline", obj=None): - """ - Retrieves a given nick (with a specified nick_type) on an object. If no nick is given, returns a list - of all nicks on the object, or the empty list. - Defaults to searching the current object. - """ - if not obj: - # defaults to the current object - obj = self.obj - if nick: - query = self.NickClass.objects.filter(db_obj=obj, db_nick__iexact=nick, db_type__iexact=nick_type) - query = query.values_list("db_real", flat=True) - if query.count(): - return query[0] - else: - return nick - else: - return self.NickClass.objects.filter(db_obj=obj) - def has(self, nick, nick_type="inputline", obj=None): - """ - Returns true/false if this nick and nick_type is defined on the given - object or not. If no obj is given, default to the current object the - handler is defined on. + def delete(self, *args, **kwargs): + "alias wrapper" + self.remove(self, *args, **kwargs) + + def get(self, nick=None, nick_type="inputline", default=None): """ - if not obj: - obj = self.obj - return self.NickClass.objects.filter(db_obj=obj, db_nick__iexact=nick, db_type__iexact=nick_type).count() + Retrieves a given nick replacement based on the input nick. If + given but no matching conversion was found, returns + original input or default if given + If no nick is given, returns a list of all matching nick + objects (LiteAttributes) on the object, or the empty list. + """ + nick = nick.strip().lower() if nick!=None else None + nick_type = "%s%s" % (self.prefix, nick_type.strip().lower()) + if nick: + nicks = _GA(self.obj, "db_liteattributes").objects.filter(db_key=nick, db_category=nick_type).prefetch_related("db_data") + default = default if default!=None else nick + return nicks[0].db_data if nicks else default + else: + return list(self.obj.db_liteattributes.all()) #------------------------------------------------------------ From c0b5c506a4a8ba68a8cab82bc6dc6e52e59a6db5 Mon Sep 17 00:00:00 2001 From: Griatch Date: Fri, 12 Jul 2013 15:34:54 +0200 Subject: [PATCH 29/49] Removed a lot of old references to Aliases and Nicks. Still failing on @puppet. --- src/commands/default/building.py | 34 ++++----- src/locks/lockfuncs.py | 2 +- src/objects/objects.py | 2 +- src/typeclasses/models.py | 115 +++++++++++++++++-------------- src/utils/create.py | 2 +- 5 files changed, 85 insertions(+), 70 deletions(-) diff --git a/src/commands/default/building.py b/src/commands/default/building.py index 8492d41dfb..076714c56c 100644 --- a/src/commands/default/building.py +++ b/src/commands/default/building.py @@ -123,7 +123,7 @@ class CmdSetObjAlias(MuxCommand): return if self.rhs == None: # no =, so we just list aliases on object. - aliases = obj.aliases + aliases = obj.aliases.all() if aliases: caller.msg("Aliases for '%s': %s" % (obj.key, ", ".join(aliases))) else: @@ -136,22 +136,22 @@ class CmdSetObjAlias(MuxCommand): if not self.rhs: # we have given an empty =, so delete aliases - old_aliases = obj.aliases + old_aliases = obj.aliases.all() if old_aliases: caller.msg("Cleared aliases from %s: %s" % (obj.key, ", ".join(old_aliases))) - del obj.dbobj.aliases + obj.dbobj.db_aliases.clear() else: caller.msg("No aliases to clear.") return # merge the old and new aliases (if any) - old_aliases = obj.aliases + old_aliases = obj.aliases.all() new_aliases = [alias.strip().lower() for alias in self.rhs.split(',') if alias.strip()] # make the aliases only appear once old_aliases.extend(new_aliases) aliases = list(set(old_aliases)) # save back to object. - obj.aliases = aliases + obj.aliases.add(aliases) # we treat this as a re-caching (relevant for exits to re-build their exit commands with the correct aliases) caller.msg("Aliases for '%s' are now set to %s." % (obj.key, ", ".join(obj.aliases))) @@ -191,7 +191,7 @@ class CmdCopy(ObjManipCommand): if not from_obj: return to_obj_name = "%s_copy" % from_obj_name - to_obj_aliases = ["%s_copy" % alias for alias in from_obj.aliases] + to_obj_aliases = ["%s_copy" % alias for alias in from_obj.aliases.all()] copiedobj = ObjectDB.objects.copy_object(from_obj, new_key=to_obj_name, new_aliases=to_obj_aliases) if copiedobj: @@ -598,8 +598,8 @@ class CmdDig(ObjManipCommand): aliases=room["aliases"], report_to=caller) new_room.locks.add(lockstring) alias_string = "" - if new_room.aliases: - alias_string = " (%s)" % ", ".join(new_room.aliases) + if new_room.aliases.all(): + alias_string = " (%s)" % ", ".join(new_room.aliases.all()) room_string = "Created room %s(%s)%s of type %s." % (new_room, new_room.dbref, alias_string, typeclass) @@ -626,8 +626,8 @@ class CmdDig(ObjManipCommand): aliases=to_exit["aliases"], locks=lockstring, destination=new_room, report_to=caller) alias_string = "" - if new_to_exit.aliases: - alias_string = " (%s)" % ", ".join(new_to_exit.aliases) + if new_to_exit.aliases.all(): + alias_string = " (%s)" % ", ".join(new_to_exit.aliases.all()) exit_to_string = "\nCreated Exit from %s to %s: %s(%s)%s." exit_to_string = exit_to_string % (location.name, new_room.name, new_to_exit, new_to_exit.dbref, alias_string) @@ -651,8 +651,8 @@ class CmdDig(ObjManipCommand): new_room, aliases=back_exit["aliases"], locks=lockstring, destination=location, report_to=caller) alias_string = "" - if new_back_exit.aliases: - alias_string = " (%s)" % ", ".join(new_back_exit.aliases) + if new_back_exit.aliases.all(): + alias_string = " (%s)" % ", ".join(new_back_exit.aliases.all()) exit_back_string = "\nCreated Exit back from %s to %s: %s(%s)%s." exit_back_string = exit_back_string % (new_room.name, location.name, new_back_exit, new_back_exit.dbref, alias_string) @@ -979,7 +979,7 @@ class CmdName(ObjManipCommand): obj.name = newname astring = "" if aliases: - obj.aliases = aliases + [obj.aliases.add(alias) for alias in aliases] astring = " (%s)" % (", ".join(aliases)) # fix for exits - we need their exit-command to change name too if obj.destination: @@ -1037,7 +1037,7 @@ class CmdOpen(ObjManipCommand): if old_destination.id != destination.id: # reroute the old exit. exit_obj.destination = destination - exit_obj.aliases = exit_aliases + [exit_obj.aliases.add(alias) for alias in exit_aliases] string += " Rerouted its old destination '%s' to '%s' and changed aliases." % \ (old_destination.name, destination.name) else: @@ -1568,8 +1568,8 @@ class CmdExamine(ObjManipCommand): """ string = "\n{wName/key{n: {c%s{n (%s)" % (obj.name, obj.dbref) - if hasattr(obj, "aliases") and obj.aliases: - string += "\n{wAliases{n: %s" % (", ".join(utils.make_iter(obj.aliases))) + if hasattr(obj, "aliases") and obj.aliases.all(): + string += "\n{wAliases{n: %s" % (", ".join(utils.make_iter(obj.aliases.all()))) if hasattr(obj, "sessid") and obj.sessid: string += "\n{wsession{n: %s" % obj.sessid elif hasattr(obj, "sessions") and obj.sessions: @@ -1785,7 +1785,7 @@ class CmdFind(MuxCommand): nresults = results.count() if not nresults: # no matches on the keys. Try aliases instead. - results = results = ObjectDB.alias_set.related.model.objects.filter(db_key=searchstring) + results = ObjectDB.db_aliases.filter(db_key=searchstring) if "room" in switches: results = results.filter(db_obj__db_location__isnull=True) if "exit" in switches: diff --git a/src/locks/lockfuncs.py b/src/locks/lockfuncs.py index 162623c838..158d37d435 100644 --- a/src/locks/lockfuncs.py +++ b/src/locks/lockfuncs.py @@ -420,7 +420,7 @@ def holds(accessing_obj, accessed_obj, *args, **kwargs): return True objid = objid.lower() return any((True for obj in contents - if obj.key.lower() == objid or objid in [al.lower() for al in obj.aliases])) + if obj.key.lower() == objid or objid in [al.lower() for al in obj.aliases.all()])) if not args: # holds() - check if accessed_obj or accessed_obj.obj is held by accessing_obj try: diff --git a/src/objects/objects.py b/src/objects/objects.py index 6a748cdbb3..aa83900758 100644 --- a/src/objects/objects.py +++ b/src/objects/objects.py @@ -910,7 +910,7 @@ class Exit(Object): # create an exit command. cmd = ExitCommand(key=exidbobj.db_key.strip().lower(), - aliases=exidbobj.aliases, + aliases=exidbobj.aliases.all(), locks=str(exidbobj.locks), auto_help=False, destination=exidbobj.db_destination, diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index fe3e992eba..2995a39023 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -365,27 +365,29 @@ class TagHandler(object): def add(self, tag, category=None, data=None): "Add a new tag to the handler" - tag = tag.strip().lower() if tag!=None else None - category = "%s%s" % (self.prefix, category.strip.lower()) if category!=None else None - data = str(data) if data!=None else None - # this will only create tag if no matches existed beforehand (it will overload - # data on an existing tag since that is not considered part of making the tag unique) - tagobj = Tag.objects.create_tag(key=tag, category=category, data=data) - self.obj.db_tags.add(tagobj) + for tag in make_iter(tag): + tag = tag.strip().lower() if tag!=None else None + category = "%s%s" % (self.prefix, category.strip.lower()) if category!=None else None + data = str(data) if data!=None else None + # this will only create tag if no matches existed beforehand (it will overload + # data on an existing tag since that is not considered part of making the tag unique) + tagobj = Tag.objects.create_tag(key=tag, category=category, data=data) + self.obj.db_tags.add(tagobj) def remove(self, tag, category=None): "Remove a tag from the handler" - tag = tag.strip().lower() if tag!=None else None - category = "%s%s" % (self.prefix, category.strip.lower()) if category!=None else None - #TODO This does not delete the tag object itself. Maybe it should do that when no - # objects reference the tag anymore? - tagobj = self.obj.db_tags.filter(db_key=tag, db_category=category) - if tagobj: - self.obj.remove(tagobj[0]) + for tag in make_iter(tag): + tag = tag.strip().lower() if tag!=None else None + category = "%s%s" % (self.prefix, category.strip.lower()) if category!=None else None + #TODO This does not delete the tag object itself. Maybe it should do that when no + # objects reference the tag anymore? + tagobj = self.obj.db_tags.filter(db_key=tag, db_category=category) + if tagobj: + self.obj.remove(tagobj[0]) def all(self): "Get all tags in this handler" - return self.obj.db_tags.all().get_values("db_key") + return self.obj.db_tags.all().values_list("db_key") def __str__(self): return ",".join(self.all()) @@ -412,21 +414,23 @@ class AliasHandler(object): "Add a new nick to the handler" if not alias or not alias.strip(): return - alias = alias.strip() - # create a unique tag only if it didn't already exist - aliasobj = Tag.objects.create_tag(key=alias, category=self.category) - self.obj.db_tags.add(aliasobj) + for al in make_iter(alias): + al = al.strip() + # create a unique tag only if it didn't already exist + aliasobj = Tag.objects.create_tag(key=al, category=self.category) + self.obj.db_tags.add(aliasobj) def remove(self, alias): "Remove alias from handler." - aliasobj = Tag.objects.filter(db_key__iexact=alias.strip(), category=self.category).count() - #TODO note that this doesn't delete the tag itself. We might want to do this when no object - # uses it anymore ... - self.obj.db_tags.remove(aliasobj) + for alias in make_iter(alias): + aliasobj = Tag.objects.filter(db_key__iexact=alias.strip(), category=self.category).count() + #TODO note that this doesn't delete the tag itself. We might want to do this when no object + # uses it anymore ... + self.obj.db_tags.remove(aliasobj) def all(self): "Get all aliases in this handler" - return self.obj.db_tags.filter(db_category=self.category).get_values("db_key") + return list(self.obj.db_tags.filter(db_category=self.category).values_list("db_key")) def __str__(self): return ",".join(self.all()) @@ -466,27 +470,29 @@ class NickHandler(object): """ if not nick or not nick.strip(): return - nick = nick.strip() - real = realname - nick_type = "%s%s" % (self.prefix, nick_type.strip().lower()) - query = self.obj.db_liteattributes.filter(db_key__iexact=nick, db_category__iexact=nick_type) - if query.count(): - old_nick = query[0] - old_nick.db_data = real - old_nick.save() - else: - new_nick = LiteAttribute(db_key=nick, db_category=nick_type, db_data=real) - new_nick.save() - self.obj.db_liteattributes.add(new_nick) + for nick in make_iter(nick): + nick = nick.strip() + real = realname + nick_type = "%s%s" % (self.prefix, nick_type.strip().lower()) + query = self.obj.db_liteattributes.filter(db_key__iexact=nick, db_category__iexact=nick_type) + if query.count(): + old_nick = query[0] + old_nick.db_data = real + old_nick.save() + else: + new_nick = LiteAttribute(db_key=nick, db_category=nick_type, db_data=real) + new_nick.save() + self.obj.db_liteattributes.add(new_nick) def remove(self, nick, nick_type="inputline"): "Removes a previously stored nick" - nick = nick.strip() - nick_type = "%s%s" % (self.prefix, nick_type.strip().lower()) - query = self.obj.liteattributes.filter(db_key__iexact=nick, db_category__iexact=nick_type) - if query.count(): - # remove the found nick(s) - query.delete() + for nick in make_iter(nick): + nick = nick.strip() + nick_type = "%s%s" % (self.prefix, nick_type.strip().lower()) + query = self.obj.liteattributes.filter(db_key__iexact=nick, db_category__iexact=nick_type) + if query.count(): + # remove the found nick(s) + query.delete() def delete(self, *args, **kwargs): "alias wrapper" @@ -500,14 +506,23 @@ class NickHandler(object): If no nick is given, returns a list of all matching nick objects (LiteAttributes) on the object, or the empty list. """ - nick = nick.strip().lower() if nick!=None else None - nick_type = "%s%s" % (self.prefix, nick_type.strip().lower()) - if nick: - nicks = _GA(self.obj, "db_liteattributes").objects.filter(db_key=nick, db_category=nick_type).prefetch_related("db_data") - default = default if default!=None else nick - return nicks[0].db_data if nicks else default - else: - return list(self.obj.db_liteattributes.all()) + returns = [] + for nick in make_iter(nick): + nick = nick.strip().lower() if nick!=None else None + nick_type = "%s%s" % (self.prefix, nick_type.strip().lower()) + if nick: + nicks = _GA(self.obj, "db_liteattributes").objects.filter(db_key=nick, db_category=nick_type).prefetch_related("db_data") + default = default if default!=None else nick + return nicks[0].db_data if nicks else default + else: + returns.extend(list(self.obj.db_liteattributes.all())) + return returns + + def all(self): + "Get all nicks in this handler" + return list(self.obj.db_nicks.filter(db_category=self.category).values_list("db_key")) + + #------------------------------------------------------------ diff --git a/src/utils/create.py b/src/utils/create.py index 32e07dfa7c..3772538b08 100644 --- a/src/utils/create.py +++ b/src/utils/create.py @@ -129,7 +129,7 @@ def create_object(typeclass, key=None, location=None, if locks: new_object.locks.add(locks) if aliases: - new_object.aliases = aliases + new_object.aliases.add(aliases) # perform a move_to in order to display eventual messages. if home: From 45706f598a003ecad1b75e755c20a53588882696 Mon Sep 17 00:00:00 2001 From: Griatch Date: Fri, 12 Jul 2013 15:57:46 +0200 Subject: [PATCH 30/49] Fixed remaining issues so the login process works. --- ev.py | 2 +- src/commands/default/general.py | 7 +++---- src/objects/models.py | 6 +++--- src/scripts/models.py | 2 +- src/typeclasses/models.py | 11 +++++++++-- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/ev.py b/ev.py index 6518425155..81e9968ea2 100644 --- a/ev.py +++ b/ev.py @@ -119,7 +119,7 @@ from src.help.models import HelpEntry from src.typeclasses.models import Attribute # players from src.players.player import Player -from src.players.models import PlayerDB, PlayerNick +from src.players.models import PlayerDB # commands from src.commands.command import Command diff --git a/src/commands/default/general.py b/src/commands/default/general.py index 1c8c313d10..d843be95f9 100644 --- a/src/commands/default/general.py +++ b/src/commands/default/general.py @@ -3,7 +3,6 @@ General Character commands usually availabe to all characters """ from django.conf import settings from src.utils import utils, prettytable -from src.objects.models import ObjectNick as Nick from src.commands.default.muxcommand import MuxCommand @@ -124,17 +123,17 @@ class CmdNick(MuxCommand): caller = self.caller switches = self.switches - nicks = Nick.objects.filter(db_obj=caller.dbobj).exclude(db_type="channel") + nicks = caller.nicks.get(category="channel") if 'list' in switches: table = prettytable.PrettyTable(["{wNickType", "{wNickname", "{wTranslates-to"]) for nick in nicks: - table.add_row([nick.db_type, nick.db_nick, nick.db_real]) + table.add_row([nick.db_category, nick.db_key, nick.db_data]) string = "{wDefined Nicks:{n\n%s" % table caller.msg(string) return if 'clearall' in switches: - nicks.delete() + caller.nicks.clear() caller.msg("Cleared all aliases.") return if not self.args or not self.lhs: diff --git a/src/objects/models.py b/src/objects/models.py index c7dccb7855..54c378fc22 100644 --- a/src/objects/models.py +++ b/src/objects/models.py @@ -643,11 +643,11 @@ class ObjectDB(TypedObject): raw_list = raw_string.split(None) raw_list = [" ".join(raw_list[:i+1]) for i in range(len(raw_list)) if raw_list[:i+1]] # fetch the nick data efficiently - nicks = self.db_lnattributes.filter(db_category__in=("object_nick_inputline", "object_nick_channel")).prefetch_related("db_key","db_data") + nicks = self.db_liteattributes.filter(db_category__in=("object_nick_inputline", "object_nick_channel")).prefetch_related("db_key","db_data") if self.has_player: - pnicks = self.player.db_lnattributes.filter( + pnicks = self.player.db_liteattributes.filter( db_category__in=("player_nick_inputline", "player_nick_channel")).prefetch_related("db_key","db_data") - nicks = nicks + pnicks + nicks = list(nicks) + list(pnicks) for nick in nicks: if nick.db_key in raw_list: raw_string = raw_string.replace(nick.db_key, nick.db_data, 1) diff --git a/src/scripts/models.py b/src/scripts/models.py index 9b47b3d0b4..ca2d2f5ef6 100644 --- a/src/scripts/models.py +++ b/src/scripts/models.py @@ -105,7 +105,7 @@ class ScriptDB(TypedObject): verbose_name = "Script" def __init__(self, *args, **kwargs): - super(ScriptDB, self).__init__(self, *args, **kwargs) + super(ScriptDB, self).__init__(*args, **kwargs) _SA(self, "tags", TagHandler(self, "script")) _SA(self, "aliases", AliasHandler(self, "script")) diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index 2995a39023..b816b2eb6d 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -384,6 +384,9 @@ class TagHandler(object): tagobj = self.obj.db_tags.filter(db_key=tag, db_category=category) if tagobj: self.obj.remove(tagobj[0]) + def clear(self): + "Remove all tags from the handler" + self.obj.db_tags.clear() def all(self): "Get all tags in this handler" @@ -423,10 +426,13 @@ class AliasHandler(object): def remove(self, alias): "Remove alias from handler." for alias in make_iter(alias): - aliasobj = Tag.objects.filter(db_key__iexact=alias.strip(), category=self.category).count() + aliasobj = self.obj.filter(db_key__iexact=alias.strip(), category=self.category) #TODO note that this doesn't delete the tag itself. We might want to do this when no object # uses it anymore ... self.obj.db_tags.remove(aliasobj) + def clear(self): + "Clear all aliases from handler" + self.obj.db_tags.remove(self.obj.filter(categery=self.category)) def all(self): "Get all aliases in this handler" @@ -589,7 +595,8 @@ class TypedObject(SharedMemoryModel): # lock handler self.locks def __init__(self, *args, **kwargs): "We must initialize the parent first - important!" - SharedMemoryModel.__init__(self, *args, **kwargs) + super(SharedMemoryModel, self).__init__(*args, **kwargs) + #SharedMemoryModel.__init__(self, *args, **kwargs) _SA(self, "dbobj", self) # this allows for self-reference _SA(self, "locks", LockHandler(self)) From 6bc16e46cc964269dfd65af6c7c85cda2cca8e0b Mon Sep 17 00:00:00 2001 From: Griatch Date: Fri, 12 Jul 2013 20:21:52 +0200 Subject: [PATCH 31/49] Made aliases work with the new handler. The location.contents updated is not working yet - this causes locational information to not be available until objects and manually initialized (e.g. by calling examine #dbref) --- src/commands/default/building.py | 4 +- src/commands/default/comms.py | 18 +-- src/commands/default/general.py | 7 +- src/commands/default/player.py | 11 +- src/commands/default/tests.py | 6 +- src/comms/managers.py | 2 +- src/objects/manager.py | 5 +- src/objects/models.py | 10 +- src/players/models.py | 6 +- .../0014_create_db_liteattributes_db_tags.py | 146 ++++++++++++++++++ src/scripts/models.py | 5 +- src/typeclasses/managers.py | 30 ++-- src/typeclasses/models.py | 62 +++++--- 13 files changed, 236 insertions(+), 76 deletions(-) create mode 100644 src/scripts/migrations/0014_create_db_liteattributes_db_tags.py diff --git a/src/commands/default/building.py b/src/commands/default/building.py index 076714c56c..2293363ef9 100644 --- a/src/commands/default/building.py +++ b/src/commands/default/building.py @@ -153,7 +153,7 @@ class CmdSetObjAlias(MuxCommand): # save back to object. obj.aliases.add(aliases) # we treat this as a re-caching (relevant for exits to re-build their exit commands with the correct aliases) - caller.msg("Aliases for '%s' are now set to %s." % (obj.key, ", ".join(obj.aliases))) + caller.msg("Aliases for '%s' are now %s." % (obj.key, str(obj.aliases))) class CmdCopy(ObjManipCommand): """ @@ -1569,7 +1569,7 @@ class CmdExamine(ObjManipCommand): string = "\n{wName/key{n: {c%s{n (%s)" % (obj.name, obj.dbref) if hasattr(obj, "aliases") and obj.aliases.all(): - string += "\n{wAliases{n: %s" % (", ".join(utils.make_iter(obj.aliases.all()))) + string += "\n{wAliases{n: %s" % (", ".join(utils.make_iter(str(obj.aliases)))) if hasattr(obj, "sessid") and obj.sessid: string += "\n{wsession{n: %s" % obj.sessid elif hasattr(obj, "sessions") and obj.sessions: diff --git a/src/commands/default/comms.py b/src/commands/default/comms.py index 4bee66e81e..700466d377 100644 --- a/src/commands/default/comms.py +++ b/src/commands/default/comms.py @@ -103,7 +103,7 @@ class CmdAddCom(MuxPlayerCommand): if alias: # create a nick and add it to the caller. - caller.nicks.add(alias, channel.key, nick_type="channel") + caller.nicks.add(alias, channel.key, category="channel") string += " You can now refer to the channel %s with the alias '%s'." self.msg(string % (channel.key, alias)) else: @@ -147,21 +147,21 @@ class CmdDelCom(MuxPlayerCommand): return chkey = channel.key.lower() # find all nicks linked to this channel and delete them - for nick in [nick for nick in caller.nicks.get(nick_type="channel") - if nick.db_real.lower() == chkey]: + for nick in [nick for nick in caller.nicks.get(category="channel") + if nick.db_data.lower() == chkey]: nick.delete() channel.disconnect_from(player) self.msg("You stop listening to channel '%s'. Eventual aliases were removed." % channel.key) return else: # we are removing a channel nick - channame = caller.nicks.get(ostring, nick_type="channel") + channame = caller.nicks.get_replace(key=ostring, category="channel") channel = find_channel(caller, channame, silent=True) if not channel: self.msg("No channel with alias '%s' was found." % ostring) else: - if caller.nicks.get(ostring, nick_type="channel", default=False): - caller.nicks.delete(ostring, nick_type="channel") + if caller.nicks.get(ostring, category="channel"): + caller.nicks.remove(ostring, category="channel") self.msg("Your alias '%s' for channel %s was cleared." % (ostring, channel.key)) else: self.msg("You had no such alias defined for this channel.") @@ -263,7 +263,7 @@ class CmdChannels(MuxPlayerCommand): comtable = prettytable.PrettyTable(["{wchannel","{wmy aliases", "{wdescription"]) for chan in subs: clower = chan.key.lower() - nicks = [nick for nick in caller.nicks.get(nick_type="channel")] + nicks = [nick for nick in caller.nicks.get(category="channel")] comtable.add_row(["%s%s" % (chan.key, chan.aliases and "(%s)" % ",".join(chan.aliases) or ""), "%s".join(nick.db_nick for nick in nicks if nick.db_real.lower()==clower()), chan.desc]) @@ -272,7 +272,7 @@ class CmdChannels(MuxPlayerCommand): # full listing (of channels caller is able to listen to) comtable = prettytable.PrettyTable(["{wsub","{wchannel","{wmy aliases","{wlocks","{wdescription"]) for chan in channels: - nicks = [nick for nick in caller.nicks.get(nick_type="channel")] + nicks = [nick for nick in caller.nicks.get(category="channel")] comtable.add_row([chan in subs and "{gYes{n" or "{rNo{n", "%s%s" % (chan.key, chan.aliases and "(%s)" % ",".join(chan.aliases) or ""), "%s".join(nick.db_nick for nick in nicks if nick.db_real.lower()==clower()), @@ -368,7 +368,7 @@ class CmdCBoot(MuxPlayerCommand): string = "%s boots %s from channel.%s" % (self.caller, player.key, reason) channel.msg(string) # find all player's nicks linked to this channel and delete them - for nick in [nick for nick in player.character.nicks.get(nick_type="channel") + for nick in [nick for nick in player.character.nicks.get(category="channel") if nick.db_real.lower() == channel.key]: nick.delete() # disconnect player diff --git a/src/commands/default/general.py b/src/commands/default/general.py index d843be95f9..99ad4c8195 100644 --- a/src/commands/default/general.py +++ b/src/commands/default/general.py @@ -151,13 +151,14 @@ class CmdNick(MuxCommand): switches = ["inputline"] string = "" for switch in switches: - oldnick = Nick.objects.filter(db_obj=caller.dbobj, db_nick__iexact=nick, db_type__iexact=switch) + oldnick = caller.nicks.get(key=nick, category=switch) + #oldnick = Nick.objects.filter(db_obj=caller.dbobj, db_nick__iexact=nick, db_type__iexact=switch) if not real: # removal of nick if oldnick: # clear the alias string += "\nNick '%s' (= '%s') was cleared." % (nick, oldnick[0].db_real) - caller.nicks.delete(nick, nick_type=switch) + caller.nicks.delete(nick, category=switch) else: string += "\nNo nick '%s' found, so it could not be removed." % nick else: @@ -166,7 +167,7 @@ class CmdNick(MuxCommand): string += "\nNick %s changed from '%s' to '%s'." % (nick, oldnick[0].db_real, real) else: string += "\nNick set: '%s' = '%s'." % (nick, real) - caller.nicks.add(nick, real, nick_type=switch) + caller.nicks.add(nick, real, category=switch) caller.msg(string) class CmdInventory(MuxCommand): diff --git a/src/commands/default/player.py b/src/commands/default/player.py index cec03d2cb2..a94de645df 100644 --- a/src/commands/default/player.py +++ b/src/commands/default/player.py @@ -465,18 +465,13 @@ class CmdPassword(MuxPlayerCommand): return oldpass = self.lhslist[0] # this is already stripped by parse() newpass = self.rhslist[0] # '' - try: - uaccount = player.user - except AttributeError: - self.msg("This is only applicable for players.") - return - if not uaccount.check_password(oldpass): + if not player.check_password(oldpass): self.msg("The specified old password isn't correct.") elif len(newpass) < 3: self.msg("Passwords must be at least three characters long.") else: - uaccount.set_password(newpass) - uaccount.save() + player.set_password(newpass) + player.save() self.msg("Password changed.") class CmdQuit(MuxPlayerCommand): diff --git a/src/commands/default/tests.py b/src/commands/default/tests.py index ccad26bf56..c9ef9cc701 100644 --- a/src/commands/default/tests.py +++ b/src/commands/default/tests.py @@ -110,9 +110,9 @@ class TestGeneral(CommandTest): self.call(general.CmdNick(), "testalias = testaliasedstring1", "Nick set:") self.call(general.CmdNick(), "/player testalias = testaliasedstring2", "Nick set:") self.call(general.CmdNick(), "/object testalias = testaliasedstring3", "Nick set:") - self.assertEqual(u"testaliasedstring1", self.char1.nicks.get("testalias")) - self.assertEqual(u"testaliasedstring2", self.char1.nicks.get("testalias", nick_type="player")) - self.assertEqual(u"testaliasedstring3", self.char1.nicks.get("testalias", nick_type="object")) + self.assertEqual(u"testaliasedstring1", self.char1.nicks.get_replace("testalias")) + self.assertEqual(u"testaliasedstring2", self.char1.nicks.get_replace("testalias", category="player")) + self.assertEqual(u"testaliasedstring3", self.char1.nicks.get_replace("testalias", category="object")) self.call(general.CmdGet(), "Obj1", "You pick up Obj1.") self.call(general.CmdDrop(), "Obj1", "You drop Obj1.") self.call(general.CmdSay(), "Testing", "You say, \"Testing\"") diff --git a/src/comms/managers.py b/src/comms/managers.py index 6362471ae0..118fcc5039 100644 --- a/src/comms/managers.py +++ b/src/comms/managers.py @@ -346,7 +346,7 @@ class ChannelManager(models.Manager): channels = self.filter(db_key__iexact=ostring) if not channels: # still no match. Search by alias. - channels = [channel for channel in self.all() if ostring.lower in [a.lower for a in channel.aliases]] + channels = [channel for channel in self.all() if ostring.lower() in [a.lower for a in channel.aliases]] return channels # diff --git a/src/objects/manager.py b/src/objects/manager.py index 6721ea3d87..ea0d3ebf8a 100644 --- a/src/objects/manager.py +++ b/src/objects/manager.py @@ -198,7 +198,8 @@ class ObjectManager(TypedObjectManager): type_restriction = typeclasses and Q(db_typeclass_path__in=make_iter(typeclasses)) or Q() if exact: # exact match - do direct search - return self.filter(cand_restriction & type_restriction & (Q(db_key__iexact=ostring) | Q(alias__db_key__iexact=ostring))).distinct() + return self.filter(cand_restriction & type_restriction & (Q(db_key__iexact=ostring) | + Q(db_tags__db_key__iexact=ostring) & Q(db_tags__db_category__iexact="object_alias"))).distinct() elif candidates: # fuzzy with candidates key_candidates = self.filter(cand_restriction & type_restriction) @@ -212,7 +213,7 @@ class ObjectManager(TypedObjectManager): if index_matches: return [obj for ind, obj in enumerate(key_candidates) if ind in index_matches] else: - alias_candidates = self.model.alias_set.related.model.objects.filter(db_obj__pk__in=candidates_id) + alias_candidates = self.filter(id__in=candidates_id, db_tags__db_category__iexact="object_alias") alias_strings = alias_candidates.values_list("db_key", flat=True) index_matches = string_partial_matching(alias_strings, ostring, ret_index=True) if index_matches: diff --git a/src/objects/models.py b/src/objects/models.py index 54c378fc22..887e7b5848 100644 --- a/src/objects/models.py +++ b/src/objects/models.py @@ -140,9 +140,9 @@ class ObjectDB(TypedObject): _SA(self, "cmdset", CmdSetHandler(self)) _GA(self, "cmdset").update(init_mode=True) _SA(self, "scripts", ScriptHandler(self)) - _SA(self, "tags", TagHandler(self, "object")) - _SA(self, "aliases", AliasHandler(self, "object")) - _SA(self, "nicks", NickHandler(self, "object")) + _SA(self, "tags", TagHandler(self, category_prefix="object_")) + _SA(self, "aliases", AliasHandler(self, category_prefix="object_")) + _SA(self, "nicks", NickHandler(self, category_prefix="object_")) # Wrapper properties to easily set database fields. These are # @property decorators that allows to access these fields using @@ -569,8 +569,8 @@ class ObjectDB(TypedObject): pnicks = self.nicks.get(category="player_nick_%s" % nicktype) nicks = nicks + pnicks for nick in nicks: - if searchdata == nick.db_nick: - searchdata = nick.db_real + if searchdata == nick.db_key: + searchdata = nick.db_data break candidates=None diff --git a/src/players/models.py b/src/players/models.py index af7d0f7f65..9f2f1eadfb 100644 --- a/src/players/models.py +++ b/src/players/models.py @@ -120,9 +120,9 @@ class PlayerDB(TypedObject, AbstractUser): # handlers _SA(self, "cmdset", CmdSetHandler(self)) _GA(self, "cmdset").update(init_mode=True) - _SA(self, "tags", TagHandler(self, "player")) - _SA(self, "aliases", AliasHandler(self, "player")) - _SA(self, "nicks", NickHandler(self, "player")) + _SA(self, "tags", TagHandler(self, category_prefix="player_")) + _SA(self, "aliases", AliasHandler(self, category_prefix="player_")) + _SA(self, "nicks", NickHandler(self, category_prefix="player_")) # Wrapper properties to easily set database fields. These are # @property decorators that allows to access these fields using diff --git a/src/scripts/migrations/0014_create_db_liteattributes_db_tags.py b/src/scripts/migrations/0014_create_db_liteattributes_db_tags.py new file mode 100644 index 0000000000..9a24cb6a0f --- /dev/null +++ b/src/scripts/migrations/0014_create_db_liteattributes_db_tags.py @@ -0,0 +1,146 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding M2M table for field db_liteattributes on 'ScriptDB' + m2m_table_name = db.shorten_name(u'scripts_scriptdb_db_liteattributes') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('scriptdb', models.ForeignKey(orm[u'scripts.scriptdb'], null=False)), + ('liteattribute', models.ForeignKey(orm[u'typeclasses.liteattribute'], null=False)) + )) + db.create_unique(m2m_table_name, ['scriptdb_id', 'liteattribute_id']) + + # Adding M2M table for field db_tags on 'ScriptDB' + m2m_table_name = db.shorten_name(u'scripts_scriptdb_db_tags') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('scriptdb', models.ForeignKey(orm[u'scripts.scriptdb'], null=False)), + ('tag', models.ForeignKey(orm[u'typeclasses.tag'], null=False)) + )) + db.create_unique(m2m_table_name, ['scriptdb_id', 'tag_id']) + + + def backwards(self, orm): + # Removing M2M table for field db_liteattributes on 'ScriptDB' + db.delete_table(db.shorten_name(u'scripts_scriptdb_db_liteattributes')) + + # Removing M2M table for field db_tags on 'ScriptDB' + db.delete_table(db.shorten_name(u'scripts_scriptdb_db_tags')) + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'objects.objectdb': { + 'Meta': {'object_name': 'ObjectDB'}, + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destinations_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_home': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'homes_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_liteattributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.LiteAttribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_location': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locations_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']", 'null': 'True', 'blank': 'True'}), + 'db_sessid': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'db_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Tag']", 'null': 'True', 'symmetrical': 'False'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'players.playerdb': { + 'Meta': {'object_name': 'PlayerDB'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_liteattributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.LiteAttribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Tag']", 'null': 'True', 'symmetrical': 'False'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'scripts.scriptdb': { + 'Meta': {'object_name': 'ScriptDB'}, + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_desc': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_interval': ('django.db.models.fields.IntegerField', [], {'default': '-1'}), + 'db_is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_liteattributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.LiteAttribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['objects.ObjectDB']", 'null': 'True', 'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_persistent': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_repeats': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'db_start_delay': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Tag']", 'null': 'True', 'symmetrical': 'False'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.attribute': { + 'Meta': {'object_name': 'Attribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.liteattribute': { + 'Meta': {'object_name': 'LiteAttribute', 'index_together': "(('db_key', 'db_category'),)"}, + 'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), + 'db_data': ('django.db.models.fields.TextField', [], {}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.tag': { + 'Meta': {'unique_together': "(('db_key', 'db_category'),)", 'object_name': 'Tag', 'index_together': "(('db_key', 'db_category'),)"}, + 'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}), + 'db_data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['scripts'] \ No newline at end of file diff --git a/src/scripts/models.py b/src/scripts/models.py index ca2d2f5ef6..8614a481fe 100644 --- a/src/scripts/models.py +++ b/src/scripts/models.py @@ -33,6 +33,7 @@ from django.contrib.contenttypes.models import ContentType from src.scripts.manager import ScriptManager __all__ = ("ScriptDB",) +_SA = object.__setattr__ #------------------------------------------------------------ @@ -106,8 +107,8 @@ class ScriptDB(TypedObject): def __init__(self, *args, **kwargs): super(ScriptDB, self).__init__(*args, **kwargs) - _SA(self, "tags", TagHandler(self, "script")) - _SA(self, "aliases", AliasHandler(self, "script")) + _SA(self, "tags", TagHandler(self, category_prefix="script_")) + _SA(self, "aliases", AliasHandler(self, category_prefix="script_")) # Wrapper properties to easily set database fields. These are diff --git a/src/typeclasses/managers.py b/src/typeclasses/managers.py index ae84ce2389..2ac277c6b1 100644 --- a/src/typeclasses/managers.py +++ b/src/typeclasses/managers.py @@ -150,18 +150,18 @@ class TagManager(models.Manager): """ Extra manager methods for Tags """ - def get_tags_on_obj(self, obj, search_key=None, category=None): + def get_tags_on_obj(self, obj, key=None, category=None): """ Get all tags on obj, optionally limited by key and/or category """ - if search_key or category: - key_cands = Q(db_key__iexact=search_key.lower().strip()) if search_key!=None else Q() - cat_cands = Q(db_category__iexact=category.lower.strip()) if search_key!=None else Q() + if key or category: + key_cands = Q(db_key__iexact=key.lower().strip()) if key!=None else Q() + cat_cands = Q(db_category__iexact=category.lower.strip()) if key!=None else Q() return _GA(obj, "db_tags").filter(cat_cands & key_cands) else: return list(_GA(obj, "db_tags").all()) - def get_tag(self, search_key=None, category=None): + def get_tag(self, key=None, category=None): """ Search and return all tags matching any combination of the search criteria. @@ -171,23 +171,23 @@ class TagManager(models.Manager): Returns a single Tag (or None) if both key and category is given, otherwise it will return a list. """ - key_cands = Q(db_key__iexact=search_key.lower().strip()) if search_key!=None else Q() - cat_cands = Q(db_category__iexact=category.lower.strip()) if search_key!=None else Q() + key_cands = Q(db_key__iexact=key.lower().strip()) if key!=None else Q() + cat_cands = Q(db_category__iexact=category.lower().strip()) if category!=None else Q() tags = self.filter(key_cands & cat_cands) - if search_key and category: + if key and category: return tags[0] if tags else None else: return list(tags) - def get_objs_with_tag(self, objclass, search_key=None, category=None): + def get_objs_with_tag(self, objclass, key=None, category=None): """ Search and return all objects of objclass that has tags matching the given search criteria. objclass (dbmodel) - the object class to search - search_key (string) - the tag identifier + key (string) - the tag identifier category (string) - the tag category """ - key_cands = Q(db_tags__db_key__iexact=search_key.lower().strip()) if search_key!=None else Q() + key_cands = Q(db_tags__db_key__iexact=key.lower().strip()) if search_key!=None else Q() cat_cands = Q(db_tags__db_category__iexact=category.lower().strip()) if category!=None else Q() return objclass.objects.filter(key_cands & cat_cands) @@ -201,14 +201,14 @@ class TagManager(models.Manager): """ data = str(data) if data!=None else None - tag = self.get_tag(search_key=key, search_category=category) + tag = self.get_tag(key=key, category=category) if tag and data != None: tag.db_data = data tag.save() elif not tag: - tag = self.objects.create(db_key=key.lower().strip() if key!=None else None, - db_category=category.lower().strip() if key!=None else None, - db_data=str(data) if data!=None else None) + tag = self.create(db_key=key.lower().strip() if key!=None else None, + db_category=category.lower().strip() if key!=None else None, + db_data=str(data) if data!=None else None) tag.save() return tag diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index b816b2eb6d..068795c524 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -390,7 +390,7 @@ class TagHandler(object): def all(self): "Get all tags in this handler" - return self.obj.db_tags.all().values_list("db_key") + return [p[0] for p in self.obj.db_tags.all().values_list("db_key")] def __str__(self): return ",".join(self.all()) @@ -415,9 +415,9 @@ class AliasHandler(object): def add(self, alias): "Add a new nick to the handler" - if not alias or not alias.strip(): - return for al in make_iter(alias): + if not al or not al.strip(): + continue al = al.strip() # create a unique tag only if it didn't already exist aliasobj = Tag.objects.create_tag(key=al, category=self.category) @@ -436,7 +436,7 @@ class AliasHandler(object): def all(self): "Get all aliases in this handler" - return list(self.obj.db_tags.filter(db_category=self.category).values_list("db_key")) + return [p[0] for p in self.obj.db_tags.filter(db_category=self.category).values_list("db_key")] def __str__(self): return ",".join(self.all()) @@ -468,10 +468,10 @@ class NickHandler(object): self.obj = obj self.prefix = "%snick_" % category_prefix.strip().lower() if category_prefix else "" - def add(self, nick, realname, nick_type="inputline"): + def add(self, nick, realname, category="inputline"): """ Assign a new nick for realname. - nick_types used by Evennia are + category used by Evennia are 'inputline', 'player', 'obj' and 'channel' """ if not nick or not nick.strip(): @@ -479,7 +479,7 @@ class NickHandler(object): for nick in make_iter(nick): nick = nick.strip() real = realname - nick_type = "%s%s" % (self.prefix, nick_type.strip().lower()) + nick_type = "%s%s" % (self.prefix, category.strip().lower()) query = self.obj.db_liteattributes.filter(db_key__iexact=nick, db_category__iexact=nick_type) if query.count(): old_nick = query[0] @@ -490,21 +490,38 @@ class NickHandler(object): new_nick.save() self.obj.db_liteattributes.add(new_nick) - def remove(self, nick, nick_type="inputline"): + def remove(self, key, category="inputline"): "Removes a previously stored nick" - for nick in make_iter(nick): + for nick in make_iter(key): nick = nick.strip() - nick_type = "%s%s" % (self.prefix, nick_type.strip().lower()) - query = self.obj.liteattributes.filter(db_key__iexact=nick, db_category__iexact=nick_type) + nick_type = "%s%s" % (self.prefix, category.strip().lower()) + query = self.obj.db_liteattributes.filter(db_key__iexact=nick, db_category__iexact=nick_type) if query.count(): # remove the found nick(s) - query.delete() + self.obj.db_liteattributes.remove(query[0]) def delete(self, *args, **kwargs): "alias wrapper" - self.remove(self, *args, **kwargs) + self.remove(*args, **kwargs) - def get(self, nick=None, nick_type="inputline", default=None): + def get(self, key=None, category="inputline"): + """ + Retrieves a given nick object based on the input key and category. + If no key is given, returns a list of all matching nick + objects (LiteAttributes) on the object, or the empty list. + """ + returns = [] + for nick in make_iter(key): + nick = nick.strip().lower() if nick!=None else None + nick_type = "%s%s" % (self.prefix, category.strip().lower()) + if nick: + nicks = _GA(self.obj, "db_liteattributes").filter(db_key=nick, db_category=nick_type) + return nicks[0] if nicks else None + else: + returns.extend(list(self.obj.db_liteattributes.all())) + return returns + + def get_replace(self, key, category="inputline", default=None): """ Retrieves a given nick replacement based on the input nick. If given but no matching conversion was found, returns @@ -513,20 +530,19 @@ class NickHandler(object): objects (LiteAttributes) on the object, or the empty list. """ returns = [] - for nick in make_iter(nick): + for nick in make_iter(key): nick = nick.strip().lower() if nick!=None else None - nick_type = "%s%s" % (self.prefix, nick_type.strip().lower()) - if nick: - nicks = _GA(self.obj, "db_liteattributes").objects.filter(db_key=nick, db_category=nick_type).prefetch_related("db_data") - default = default if default!=None else nick - return nicks[0].db_data if nicks else default - else: - returns.extend(list(self.obj.db_liteattributes.all())) + nick_type = "%s%s" % (self.prefix, category.strip().lower()) + nicks = _GA(self.obj, "db_liteattributes").filter(db_key=nick, db_category=nick_type) + default = default if default!=None else nick + returns.append(nicks[0].db_data) if nicks else returns.append(default) + if len(returns) == 1: + return returns[0] return returns def all(self): "Get all nicks in this handler" - return list(self.obj.db_nicks.filter(db_category=self.category).values_list("db_key")) + return [p[0] for p in self.obj.db_nicks.filter(db_category=self.category).values_list("db_key")] From 73a5800fbfe8d6eec518330ac354f1813384d9a8 Mon Sep 17 00:00:00 2001 From: Griatch Date: Fri, 12 Jul 2013 22:08:15 +0200 Subject: [PATCH 32/49] Fixed updates of the contentmanager. Not all command tests run yet. --- src/commands/default/system.py | 9 ++++++++ src/objects/models.py | 41 ++++++++++++++++++---------------- src/scripts/models.py | 1 - src/typeclasses/models.py | 8 +++---- src/utils/idmapper/base.py | 2 +- 5 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/commands/default/system.py b/src/commands/default/system.py index 6288b8b095..3bd453e032 100644 --- a/src/commands/default/system.py +++ b/src/commands/default/system.py @@ -213,6 +213,15 @@ def format_script_list(scripts): table.align = 'r' for script in scripts: nextrep = script.time_until_next_repeat() + print ([script.id, + (not hasattr(script, 'obj') or not script.obj) and "" or script.obj.key, + script.key, + (not hasattr(script, 'interval') or script.interval < 0) and "--" or "%ss" % script.interval, + not nextrep and "--" or "%ss" % nextrep, + (not hasattr(script, 'repeats') or not script.repeats) and "--" or "%i" % script.repeats, + script.persistent and "*" or "-", + script.typeclass_path.rsplit('.', 1)[-1], + script.desc]) table.add_row([script.id, (not hasattr(script, 'obj') or not script.obj) and "" or script.obj.key, script.key, diff --git a/src/objects/models.py b/src/objects/models.py index 887e7b5848..eca42c30c8 100644 --- a/src/objects/models.py +++ b/src/objects/models.py @@ -143,6 +143,8 @@ class ObjectDB(TypedObject): _SA(self, "tags", TagHandler(self, category_prefix="object_")) _SA(self, "aliases", AliasHandler(self, category_prefix="object_")) _SA(self, "nicks", NickHandler(self, category_prefix="object_")) + # make sure to sync the contents cache when initializing + self.contents_update() # Wrapper properties to easily set database fields. These are # @property decorators that allows to access these fields using @@ -152,6 +154,7 @@ class ObjectDB(TypedObject): # value = self.attr and del self.attr respectively (where self # is the object in question). + #TODO - make player-handler # player property (wraps db_player) #@property def __player_get(self): @@ -187,25 +190,25 @@ class ObjectDB(TypedObject): # sessid property (wraps db_sessid) #@property - def __sessid_get(self): - """ - Getter. Allows for value = self.sessid. Since sessid - is directly related to self.player, we cannot have - a sessid without a player being connected (but the - opposite could be true). - """ - if not get_field_cache(self, "sessid"): - del_field_cache(self, "sessid") - return get_field_cache(self, "sessid") - #@sessid.setter - def __sessid_set(self, sessid): - "Setter. Allows for self.player = value" - set_field_cache(self, "sessid", sessid) - #@sessid.deleter - def __sessid_del(self): - "Deleter. Allows for del self.player" - del_field_cache(self, "sessid") - sessid = property(__sessid_get, __sessid_set, __sessid_del) + #def __sessid_get(self): + # """ + # Getter. Allows for value = self.sessid. Since sessid + # is directly related to self.player, we cannot have + # a sessid without a player being connected (but the + # opposite could be true). + # """ + # if not get_field_cache(self, "sessid"): + # del_field_cache(self, "sessid") + # return get_field_cache(self, "sessid") + ##@sessid.setter + #def __sessid_set(self, sessid): + # "Setter. Allows for self.player = value" + # set_field_cache(self, "sessid", sessid) + ##@sessid.deleter + #def __sessid_del(self): + # "Deleter. Allows for del self.player" + # del_field_cache(self, "sessid") + #sessid = property(__sessid_get, __sessid_set, __sessid_del) def _db_location_handler(self, loc, old_value=None): "This handles changes to the db_location field." diff --git a/src/scripts/models.py b/src/scripts/models.py index 8614a481fe..032695c2e6 100644 --- a/src/scripts/models.py +++ b/src/scripts/models.py @@ -110,7 +110,6 @@ class ScriptDB(TypedObject): _SA(self, "tags", TagHandler(self, category_prefix="script_")) _SA(self, "aliases", AliasHandler(self, category_prefix="script_")) - # 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() diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index 068795c524..0f23c9db62 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -232,10 +232,10 @@ class Attribute(SharedMemoryModel): # def __str__(self): - return smart_str("%s(%s)" % (self.key, self.id)) + return smart_str("%s(%s)" % (_GA(self, "db_key", _GA(self, "id")))) def __unicode__(self): - return u"%s(%s)" % (self.key, self.id) + return u"%s(%s)" % (_GA(self, "db_key", _GA(self, "id"))) def access(self, accessing_obj, access_type='read', default=False): """ @@ -739,10 +739,10 @@ class TypedObject(SharedMemoryModel): return other and hasattr(other, 'dbid') and self.dbid == other.dbid def __str__(self): - return smart_str("%s" % self.key) + return smart_str("%s" % _GA(self, "db_key")) def __unicode__(self): - return u"%s" % self.key + return u"%s" % _GA(self, "db_key") def __getattribute__(self, propname): """ diff --git a/src/utils/idmapper/base.py b/src/utils/idmapper/base.py index 558d5f3d81..d0d1b3bb3c 100755 --- a/src/utils/idmapper/base.py +++ b/src/utils/idmapper/base.py @@ -98,7 +98,7 @@ class SharedMemoryModelBase(ModelBase): "Wrapper for setting database field" if hasattr(value, "dbobj"): value = _GA(value, "dbobj") - elif fname.isdigit() or fname.startswith("#"): + elif isinstance(value, basestring) and (value.isdigit() or value.startswith("#")): # we also allow setting using dbrefs, if so we try to load the matching object. # (we assume the object is of the same type as the class holding the field, if # not a custom handler must be used for that field) From 7b0c96640caf3ef91474e963a84bef258bcabcb0 Mon Sep 17 00:00:00 2001 From: Griatch Date: Fri, 12 Jul 2013 23:58:22 +0200 Subject: [PATCH 33/49] Reverting metaclass wrapper for db_key, will have to look into why it behaves strangely. --- src/commands/default/system.py | 18 +++++++++--------- src/typeclasses/models.py | 26 +++++++++++++------------- src/utils/idmapper/base.py | 1 - 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/commands/default/system.py b/src/commands/default/system.py index 3bd453e032..fe4b56bfeb 100644 --- a/src/commands/default/system.py +++ b/src/commands/default/system.py @@ -213,15 +213,15 @@ def format_script_list(scripts): table.align = 'r' for script in scripts: nextrep = script.time_until_next_repeat() - print ([script.id, - (not hasattr(script, 'obj') or not script.obj) and "" or script.obj.key, - script.key, - (not hasattr(script, 'interval') or script.interval < 0) and "--" or "%ss" % script.interval, - not nextrep and "--" or "%ss" % nextrep, - (not hasattr(script, 'repeats') or not script.repeats) and "--" or "%i" % script.repeats, - script.persistent and "*" or "-", - script.typeclass_path.rsplit('.', 1)[-1], - script.desc]) + #print ([script.id, + # (not hasattr(script, 'obj') or not script.obj) and "" or script.obj.key, + # script.key, + # (not hasattr(script, 'interval') or script.interval < 0) and "--" or "%ss" % script.interval, + # not nextrep and "--" or "%ss" % nextrep, + # (not hasattr(script, 'repeats') or not script.repeats) and "--" or "%i" % script.repeats, + # script.persistent and "*" or "-", + # script.typeclass_path.rsplit('.', 1)[-1], + # script.desc]) table.add_row([script.id, (not hasattr(script, 'obj') or not script.obj) and "" or script.obj.key, script.key, diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index 0f23c9db62..f4cd8b2219 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -635,19 +635,19 @@ class TypedObject(SharedMemoryModel): # key property (wraps db_key) #@property - #def __key_get(self): - # "Getter. Allows for value = self.key" - # return _GA(self, "db_key") - # #return get_field_cache(self, "key") - ##@key.setter - #def __key_set(self, value): - # "Setter. Allows for self.key = value" - # set_field_cache(self, "key", value) - ##@key.deleter - #def __key_del(self): - # "Deleter. Allows for del self.key" - # raise Exception("Cannot delete objectdb key!") - #key = property(__key_get, __key_set, __key_del) + def __key_get(self): + "Getter. Allows for value = self.key" + return _GA(self, "db_key") + #return get_field_cache(self, "key") + #@key.setter + def __key_set(self, value): + "Setter. Allows for self.key = value" + set_field_cache(self, "key", value) + #@key.deleter + def __key_del(self): + "Deleter. Allows for del self.key" + raise Exception("Cannot delete objectdb key!") + key = property(__key_get, __key_set, __key_del) # name property (alias to self.key) def __name_get(self): return self.key diff --git a/src/utils/idmapper/base.py b/src/utils/idmapper/base.py index d0d1b3bb3c..ad17defb7c 100755 --- a/src/utils/idmapper/base.py +++ b/src/utils/idmapper/base.py @@ -127,7 +127,6 @@ class SharedMemoryModelBase(ModelBase): fset = lambda cls, val: _set(cls, fieldname, val) fdel = lambda cls: _del(cls, fieldname) doc = "Wraps setting, saving and deleting the %s field." % fieldname - type(cls).__setattr__(cls, wrappername, property(fget, fset, fdel, doc)) # exclude some models that should not auto-create wrapper fields From aa5aeaccc32be11190e65e7eecf9b777e1e696ee Mon Sep 17 00:00:00 2001 From: Kelketek Date: Tue, 16 Jul 2013 08:33:24 -0500 Subject: [PATCH 34/49] Fixed issue with improper handling of non-unique tags and nicks. --- ...copy_nicks_to_liteattrs_aliases_to_tags.py | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py b/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py index f133b43d32..17d6456cea 100644 --- a/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py +++ b/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py @@ -2,7 +2,7 @@ import datetime from south.db import db from south.v2 import DataMigration -from django.db import models +from django.db import models, IntegrityError class Migration(DataMigration): @@ -15,21 +15,30 @@ class Migration(DataMigration): # and orm['appname.ModelName'] for models in other applications. for alias in orm['objects.Alias'].objects.all(): # convert all Aliases to tags - tag = orm.Tag(db_key=alias.db_key, db_category="object_alias", db_data=None) - tag.save() - obj = alias.db_obj - obj.db_tags.add(tag) + try: + tag = orm.Tag(db_key=alias.db_key, db_category="object_alias", db_data=None) + tag.save() + obj = alias.db_obj + obj.db_tags.add(tag) + except IntegrityError: + print "Tag already exists: %s for %s" % (alias.db_key, alias.db_obj.db_key) # convert all nicks to LiteAttrs for nick in orm['objects.ObjectNick'].objects.all(): - lattr = orm.LiteAttribute(db_key=nick.db_nick, db_category="object_nick_%s" % nick.db_type, db_data=nick.db_real) - lattr.save() - obj = nick.db_obj - obj.db_liteattributes.add(lattr) + try: + lattr = orm.LiteAttribute(db_key=nick.db_nick, db_category="object_nick_%s" % nick.db_type, db_data=nick.db_real) + lattr.save() + obj = nick.db_obj + obj.db_liteattributes.add(lattr) + except IntegrityError: + print "Nick already exists: %s for %s" % (nick.db_nick, nick.db_obj.db_key) for nick in orm['players.PlayerNick'].objects.all(): - lattr = orm.LiteAttribute(db_key=nick.db_nick, db_category="player_nick_%s" % nick.db_type, db_data=nick.db_real) - lattr.save() - obj = nick.db_obj - obj.db_liteattributes.add(lattr) + try: + lattr = orm.LiteAttribute(db_key=nick.db_nick, db_category="player_nick_%s" % nick.db_type, db_data=nick.db_real) + lattr.save() + obj = nick.db_obj + obj.db_liteattributes.add(lattr) + except IntegrityError: + print "Nick already exists: %s for %s" % (nick.db_nick, nick.db_obj.db_key) def backwards(self, orm): From 90faaf9d014e4814a901d4af690d54a0437456f7 Mon Sep 17 00:00:00 2001 From: Kelketek Date: Thu, 18 Jul 2013 08:40:48 -0500 Subject: [PATCH 35/49] Fixed some issues with the admin interface. These changes may not be the best ones for these datatypes, but they should load now... --- src/objects/admin.py | 16 ++++++++-------- src/players/admin.py | 27 ++++++++++++++++++--------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/objects/admin.py b/src/objects/admin.py index 70ee844cb2..f55b75cea2 100644 --- a/src/objects/admin.py +++ b/src/objects/admin.py @@ -7,8 +7,8 @@ from django import forms from django.conf import settings from django.contrib import admin from src.typeclasses.models import Attribute -from src.objects.models import ObjectDB, ObjectNick, Alias -from src.utils.utils import mod_import +from src.objects.models import ObjectDB +from src.typeclasses.models import Tag, LiteAttribute class AttributeInline(admin.TabularInline): @@ -16,14 +16,14 @@ class AttributeInline(admin.TabularInline): fields = ('db_key', 'db_value') extra = 0 -class NickInline(admin.TabularInline): - model = ObjectNick - fields = ('db_nick', 'db_real', 'db_type') +class TagInline(admin.TabularInline): + model = Tag + fields = ('db_key', 'db_category', 'db_data') extra = 0 -class AliasInline(admin.TabularInline): - model = Alias - fields = ("db_key",) +class LiteAttributeInline(admin.TabularInline): + model = LiteAttribute + fields = ('db_key', 'db_category', 'db_data') extra = 0 class ObjectCreateForm(forms.ModelForm): diff --git a/src/players/admin.py b/src/players/admin.py index 5012f557f6..eeed13e340 100644 --- a/src/players/admin.py +++ b/src/players/admin.py @@ -15,17 +15,20 @@ from src.players.models import PlayerDB from src.typeclasses.models import Attribute from src.utils import logger, create -# remove User itself from admin site -admin.site.unregister(User) # handle the custom User editor -class CustomUserChangeForm(UserChangeForm): +class PlayerDBChangeForm(UserChangeForm): + + class Meta: + model = PlayerDB + username = forms.RegexField(label="Username", max_length=30, regex=r'^[\w. @+-]+$', widget=forms.TextInput(attrs={'size':'30'}), error_messages = {'invalid': "This value may contain only letters, spaces, numbers and @/./+/-/_ characters."}, help_text = "30 characters or fewer. Letters, spaces, digits and @/./+/-/_ only.") + def clean_username(self): username = self.cleaned_data['username'] if username.upper() == self.instance.username.upper(): @@ -34,7 +37,12 @@ class CustomUserChangeForm(UserChangeForm): raise forms.ValidationError('A player with that name already exists.') return self.cleaned_data['username'] -class CustomUserCreationForm(UserCreationForm): + +class PlayerDBCreationForm(UserCreationForm): + + class Meta: + model = PlayerDB + username = forms.RegexField(label="Username", max_length=30, regex=r'^[\w. @+-]+$', @@ -72,6 +80,7 @@ class PlayerForm(forms.ModelForm): class Meta: model = PlayerDB + db_key = forms.RegexField(label="Username", initial="PlayerDummy", max_length=30, @@ -117,12 +126,12 @@ class PlayerInline(admin.StackedInline): extra = 1 max_num = 1 -class UserAdmin(BaseUserAdmin): +class PlayerDBAdmin(BaseUserAdmin): "This is the main creation screen for Users/players" list_display = ('username','email', 'is_staff', 'is_superuser') - form = CustomUserChangeForm - add_form = CustomUserCreationForm + form = PlayerDBChangeForm + add_form = PlayerDBCreationForm inlines = [PlayerInline] add_form_template = "admin/players/add_form.html" change_form_template = "admin/players/change_form.html" @@ -145,7 +154,7 @@ class UserAdmin(BaseUserAdmin): # TODO! Remove User reference! def save_formset(self, request, form, formset, change): "Run all hooks on the player object" - super(UserAdmin, self).save_formset(request, form, formset, change) + super(PlayerDBAdmin, self).save_formset(request, form, formset, change) userobj = form.instance playerobj = userobj.get_profile() playerobj.name = userobj.username @@ -158,4 +167,4 @@ class UserAdmin(BaseUserAdmin): typeclass=typeclass, player_dbobj=playerobj) -admin.site.register(User, UserAdmin) +admin.site.register(PlayerDB, PlayerDBAdmin) \ No newline at end of file From da097a88d997477bd66f0b8fea6d285bacc0005e Mon Sep 17 00:00:00 2001 From: Kelketek Date: Fri, 19 Jul 2013 17:13:57 -0500 Subject: [PATCH 36/49] Fixed an issue with case sensitivity in table names for the migrations. Fixed issue with transactions when converting nicks and aliases. --- .../migrations/0024_rename_tmp_to_player.py | 2 +- ...4_copy_nicks_to_liteattrs_aliases_to_tags.py | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/players/migrations/0024_rename_tmp_to_player.py b/src/players/migrations/0024_rename_tmp_to_player.py index 85db97515e..f89371f9ef 100644 --- a/src/players/migrations/0024_rename_tmp_to_player.py +++ b/src/players/migrations/0024_rename_tmp_to_player.py @@ -8,7 +8,7 @@ class Migration(SchemaMigration): def forwards(self, orm): - db.rename_table('players_PlayerDBtmp', 'players_PlayerDB') + db.rename_table('players_playerdbtmp', 'players_playerdb') def backwards(self, orm): raise RuntimeError("Cannot revert this migration.") diff --git a/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py b/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py index 17d6456cea..1192ca32da 100644 --- a/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py +++ b/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py @@ -13,32 +13,49 @@ class Migration(DataMigration): # Note: Don't use "from appname.models import ModelName". # Use orm.ModelName to refer to models in this application, # and orm['appname.ModelName'] for models in other applications. + + # Each alias and nick is its own case. By default, this function starts + # in a transaction, so we'll close that and make our own transactions. + db.commit_transaction() + for alias in orm['objects.Alias'].objects.all(): # convert all Aliases to tags try: + db.start_transaction() tag = orm.Tag(db_key=alias.db_key, db_category="object_alias", db_data=None) tag.save() obj = alias.db_obj obj.db_tags.add(tag) + db.commit_transaction() except IntegrityError: + db.commit_transaction() print "Tag already exists: %s for %s" % (alias.db_key, alias.db_obj.db_key) # convert all nicks to LiteAttrs for nick in orm['objects.ObjectNick'].objects.all(): try: + db.start_transaction() lattr = orm.LiteAttribute(db_key=nick.db_nick, db_category="object_nick_%s" % nick.db_type, db_data=nick.db_real) lattr.save() obj = nick.db_obj obj.db_liteattributes.add(lattr) + db.commit_transaction() except IntegrityError: + db.commit_transaction() print "Nick already exists: %s for %s" % (nick.db_nick, nick.db_obj.db_key) for nick in orm['players.PlayerNick'].objects.all(): try: + db.start_transaction() lattr = orm.LiteAttribute(db_key=nick.db_nick, db_category="player_nick_%s" % nick.db_type, db_data=nick.db_real) lattr.save() obj = nick.db_obj obj.db_liteattributes.add(lattr) + db.commit_transaction() except IntegrityError: + db.commit_transaction() print "Nick already exists: %s for %s" % (nick.db_nick, nick.db_obj.db_key) + # South expects the migration to be transaction managed. So start up a + # new transaction for it to close immediately when it exits this function. + db.commit_transaction() def backwards(self, orm): From 083642b2dd82779def5a3ff455e2471b1f64af4b Mon Sep 17 00:00:00 2001 From: Kelketek Date: Fri, 19 Jul 2013 17:22:46 -0500 Subject: [PATCH 37/49] Fixed an issue with the backend authentication not getting the proper user model. --- src/web/backends.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/web/backends.py b/src/web/backends.py index 21c5f9a100..6365d9e904 100644 --- a/src/web/backends.py +++ b/src/web/backends.py @@ -1,5 +1,5 @@ from django.contrib.auth.backends import ModelBackend -from django.contrib.auth.models import User +from django.contrib.auth import get_user_model class CaseInsensitiveModelBackend(ModelBackend): """ @@ -7,6 +7,7 @@ class CaseInsensitiveModelBackend(ModelBackend): generally expected. This backend supports case insensitive username authentication. """ def authenticate(self, username=None, password=None): + User = get_user_model() try: user = User.objects.get(username__iexact=username) if user.check_password(password): From 40ff9eaa67dd700ef2764bd7ab82c4d726ab8685 Mon Sep 17 00:00:00 2001 From: Kelketek Date: Sat, 20 Jul 2013 12:10:47 -0500 Subject: [PATCH 38/49] Removed has_perm function from typeclass model. This function is looked for by django admin and expected to do something different, and it was deprecated anyway. --- src/typeclasses/models.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index f4cd8b2219..ea99c0bb11 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -1403,11 +1403,6 @@ class TypedObject(SharedMemoryModel): """ return self.locks.check(accessing_obj, access_type=access_type, default=default) - def has_perm(self, accessing_obj, access_type): - "Alias to access" - logger.log_depmsg("has_perm() is deprecated. Use access() instead.") - return self.access(accessing_obj, access_type) - def check_permstring(self, permstring): """ This explicitly checks if we hold particular permission without involving From fbd1b5223b8d44b95e4d5b396d984abf114f867f Mon Sep 17 00:00:00 2001 From: Kelketek Date: Sat, 20 Jul 2013 12:42:10 -0500 Subject: [PATCH 39/49] Some refinements to the admin interface for objects and players. --- src/objects/admin.py | 1 + src/players/admin.py | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objects/admin.py b/src/objects/admin.py index f55b75cea2..849691fcf2 100644 --- a/src/objects/admin.py +++ b/src/objects/admin.py @@ -64,6 +64,7 @@ class ObjectDBAdmin(admin.ModelAdmin): list_display_links = ('id', 'db_key') ordering = ['db_player', 'db_typeclass_path', 'id'] search_fields = ['^db_key', 'db_typeclass_path'] + raw_id_fields = ('db_destination', 'db_location', 'db_home') save_as = True save_on_top = True diff --git a/src/players/admin.py b/src/players/admin.py index eeed13e340..55b2f47b9a 100644 --- a/src/players/admin.py +++ b/src/players/admin.py @@ -135,7 +135,6 @@ class PlayerDBAdmin(BaseUserAdmin): inlines = [PlayerInline] add_form_template = "admin/players/add_form.html" change_form_template = "admin/players/change_form.html" - change_list_template = "admin/players/change_list.html" fieldsets = ( (None, {'fields': ('username', 'password', 'email')}), ('Website profile', {'fields': ('first_name', 'last_name'), @@ -167,4 +166,4 @@ class PlayerDBAdmin(BaseUserAdmin): typeclass=typeclass, player_dbobj=playerobj) -admin.site.register(PlayerDB, PlayerDBAdmin) \ No newline at end of file +admin.site.register(PlayerDB, PlayerDBAdmin) From 3c496af6ad3560a8fbc1d041d4ce0c281577c6e0 Mon Sep 17 00:00:00 2001 From: Kelketek Date: Sat, 20 Jul 2013 13:17:41 -0500 Subject: [PATCH 40/49] Migrations fixes revealed as necessary by the admin pages, which were also fixed. --- src/objects/admin.py | 7 +- src/players/admin.py | 5 +- .../migrations/0027_permissions_and_groups.py | 93 +++++++++++++++++++ ...copy_nicks_to_liteattrs_aliases_to_tags.py | 2 +- 4 files changed, 99 insertions(+), 8 deletions(-) create mode 100644 src/players/migrations/0027_permissions_and_groups.py diff --git a/src/objects/admin.py b/src/objects/admin.py index 849691fcf2..f57d6faf31 100644 --- a/src/objects/admin.py +++ b/src/objects/admin.py @@ -46,6 +46,7 @@ class ObjectCreateForm(forms.ModelForm): required=False, widget=forms.TextInput(attrs={'size':'78'}), help_text="Most non-character objects don't need a cmdset and can leave this field blank.") + raw_id_fields = ('db_destination', 'db_location', 'db_home') @@ -60,7 +61,7 @@ class ObjectEditForm(ObjectCreateForm): class ObjectDBAdmin(admin.ModelAdmin): - list_display = ('id', 'db_key', 'db_location', 'db_player', 'db_typeclass_path') + list_display = ('id', 'db_key', 'db_player', 'db_typeclass_path') list_display_links = ('id', 'db_key') ordering = ['db_player', 'db_typeclass_path', 'id'] search_fields = ['^db_key', 'db_typeclass_path'] @@ -69,7 +70,7 @@ class ObjectDBAdmin(admin.ModelAdmin): save_as = True save_on_top = True list_select_related = True - list_filter = ('db_permissions', 'db_location', 'db_typeclass_path') + list_filter = ('db_permissions', 'db_typeclass_path') # editing fields setup @@ -91,7 +92,7 @@ class ObjectDBAdmin(admin.ModelAdmin): add_fieldsets = ( (None, { 'fields': (('db_key','db_typeclass_path'), 'db_permissions', - ('db_location', 'db_home'), 'db_destination','db_cmdset_storage' + ('db_location', 'db_home'), 'db_destination', 'db_cmdset_storage' )}), ) def get_fieldsets(self, request, obj=None): diff --git a/src/players/admin.py b/src/players/admin.py index 55b2f47b9a..bac20f2a2f 100644 --- a/src/players/admin.py +++ b/src/players/admin.py @@ -129,12 +129,9 @@ class PlayerInline(admin.StackedInline): class PlayerDBAdmin(BaseUserAdmin): "This is the main creation screen for Users/players" - list_display = ('username','email', 'is_staff', 'is_superuser') + list_display = ('username', 'email', 'is_staff', 'is_superuser') form = PlayerDBChangeForm add_form = PlayerDBCreationForm - inlines = [PlayerInline] - add_form_template = "admin/players/add_form.html" - change_form_template = "admin/players/change_form.html" fieldsets = ( (None, {'fields': ('username', 'password', 'email')}), ('Website profile', {'fields': ('first_name', 'last_name'), diff --git a/src/players/migrations/0027_permissions_and_groups.py b/src/players/migrations/0027_permissions_and_groups.py new file mode 100644 index 0000000000..297bacd3d2 --- /dev/null +++ b/src/players/migrations/0027_permissions_and_groups.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + db.rename_table('players_playerdbtmp_groups', 'players_playerdb_groups') + db.rename_column('players_playerdb_groups', 'playerdbtmp_id', 'playerdb_id') + db.rename_table('players_playerdbtmp_user_permissions', 'players_playerdb_user_permissions') + db.rename_column('players_playerdb_user_permissions', 'playerdbtmp_id', 'playerdb_id') + + def backwards(self, orm): + db.rename_table('players_playerdb_groups', 'players_playerdbtmp_groups') + db.rename_column('players_playerdbtmp_groups', 'playerdb_id', 'playerdbtmp_id') + db.rename_table('players_playerdb_user_permissions', 'players_playerdbtmp_user_permissions') + db.rename_column('players_playerdbtmp_user_permissions', 'playerdb_id', 'playerdbtmp_id') + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'players.playerdb': { + 'Meta': {'object_name': 'PlayerDB'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_liteattributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.LiteAttribute']", 'null': 'True', 'symmetrical': 'False'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), + 'db_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Tag']", 'null': 'True', 'symmetrical': 'False'}), + 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'typeclasses.attribute': { + 'Meta': {'object_name': 'Attribute'}, + 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), + 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.liteattribute': { + 'Meta': {'object_name': 'LiteAttribute', 'index_together': "(('db_key', 'db_category'),)"}, + 'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), + 'db_data': ('django.db.models.fields.TextField', [], {}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + u'typeclasses.tag': { + 'Meta': {'unique_together': "(('db_key', 'db_category'),)", 'object_name': 'Tag', 'index_together': "(('db_key', 'db_category'),)"}, + 'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}), + 'db_data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + } + } + + complete_apps = ['players'] diff --git a/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py b/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py index 1192ca32da..5c6280f81c 100644 --- a/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py +++ b/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py @@ -55,7 +55,7 @@ class Migration(DataMigration): print "Nick already exists: %s for %s" % (nick.db_nick, nick.db_obj.db_key) # South expects the migration to be transaction managed. So start up a # new transaction for it to close immediately when it exits this function. - db.commit_transaction() + db.start_transaction() def backwards(self, orm): From 89aebfc13fda98b1023a8f73552707df107b8232 Mon Sep 17 00:00:00 2001 From: Kelketek Date: Sat, 20 Jul 2013 15:45:16 -0500 Subject: [PATCH 41/49] Made migrations compatible with new user model when creating from scratch. --- src/objects/migrations/0001_initial.py | 17 +++++-- ...02_auto__del_field_objattribute_db_mode.py | 17 +++++-- ...auto__add_field_objectdb_db_destination.py | 17 +++++-- .../0004_rename_nick_to_objectnick.py | 17 +++++-- .../0005_add_object_default_locks.py | 17 +++++-- src/objects/migrations/0006_add_view_lock.py | 17 +++++-- ...set_storage__chg_field_objectdb_db_lock.py | 17 +++++-- src/objects/migrations/0008_auto.py | 17 +++++-- .../migrations/0009_converting_attributes.py | 17 +++++-- .../migrations/0010_converting_attributes.py | 17 +++++-- ...typeclass_and_cmdset_to_new_api_default.py | 17 +++++-- .../migrations/0012_index_objattr_values.py | 17 +++++-- .../migrations/0013_revert_objattr_index.py | 17 +++++-- ...uto__chg_field_objectdb_db_lock_storage.py | 17 +++++-- ..._chg_field_objattribute_db_lock_storage.py | 17 +++++-- src/objects/migrations/0016_add_sessid.py | 17 +++++-- .../migrations/0017_rename_default_cmdsets.py | 17 +++++-- .../migrations/0018_add_picklefield.py | 17 +++++-- .../migrations/0019_convert_attrdata.py | 17 +++++-- .../0020_remove_old_attr_value_field.py | 17 +++++-- .../migrations/0021_auto__del_objattribute.py | 17 +++++-- src/players/migrations/0001_initial.py | 19 +++++-- ...auto__del_field_playerattribute_db_mode.py | 17 +++++-- ...o__add_field_playerdb_db_cmdset_storage.py | 17 +++++-- ...nique_playernick_db_nick_db_type_db_obj.py | 17 +++++-- .../migrations/0005_adding_player_cmdset.py | 17 +++++-- ...set_storage__chg_field_playerdb_db_lock.py | 17 +++++-- src/players/migrations/0007_auto.py | 17 +++++-- .../migrations/0008_converting_attributes.py | 17 +++++-- .../migrations/0009_converting_attributes.py | 17 +++++-- ...typeclass_and_cmdset_to_new_api_default.py | 17 +++++-- .../0011_addin_is_connected_field.py | 17 +++++-- ...uto__chg_field_playerdb_db_lock_storage.py | 17 +++++-- ...g_field_playerattribute_db_lock_storage.py | 17 +++++-- .../0014_add_attr__playable_characters.py | 17 +++++-- src/players/migrations/0015_removing_obj.py | 17 +++++-- .../migrations/0016_rename_default_cmdsets.py | 17 +++++-- .../migrations/0017_add_picklefield.py | 17 +++++-- .../migrations/0018_convert_attrdata.py | 17 +++++-- .../0019_remove_old_attr_value_field.py | 17 +++++-- .../0020_auto__del_playerattribute.py | 17 +++++-- .../migrations/0021_add_playerdbtmp.py | 50 ++++++------------- .../0022_copy_user_profile_to_tmp.py | 17 +++++-- .../migrations/0023_delete_old_profile.py | 17 +++++-- src/scripts/migrations/0001_initial.py | 20 ++++++-- ...auto__del_field_scriptattribute_db_mode.py | 17 +++++-- ...k_storage__chg_field_scriptdb_db_permis.py | 17 +++++-- src/scripts/migrations/0004_auto.py | 17 +++++-- .../migrations/0005_converting_attributes.py | 17 +++++-- .../migrations/0006_converting_attributes.py | 17 +++++-- .../0007_typeclass_to_new_api_default.py | 17 +++++-- ...uto__chg_field_scriptdb_db_lock_storage.py | 17 +++++-- ...g_field_scriptattribute_db_lock_storage.py | 17 +++++-- .../migrations/0010_add_picklefield.py | 17 +++++-- .../migrations/0011_convert_attrdata.py | 17 +++++-- .../0012_remove_old_attr_value_field.py | 17 +++++-- .../0013_auto__del_scriptattribute.py | 17 +++++-- .../migrations/0002_fix_config_value.py | 2 + .../migrations/0002_resave_attrs.py | 17 +++++-- 59 files changed, 819 insertions(+), 207 deletions(-) diff --git a/src/objects/migrations/0001_initial.py b/src/objects/migrations/0001_initial.py index dc5e35441f..ceae227c74 100644 --- a/src/objects/migrations/0001_initial.py +++ b/src/objects/migrations/0001_initial.py @@ -4,6 +4,17 @@ from south.db import db from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -90,8 +101,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -159,7 +170,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/objects/migrations/0002_auto__del_field_objattribute_db_mode.py b/src/objects/migrations/0002_auto__del_field_objattribute_db_mode.py index 6c17ca99a6..521fcc9d96 100644 --- a/src/objects/migrations/0002_auto__del_field_objattribute_db_mode.py +++ b/src/objects/migrations/0002_auto__del_field_objattribute_db_mode.py @@ -49,6 +49,17 @@ class PackedDBobject(object): def __unicode__(self): return u"%s(#%s)" % (self.key, self.id) +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -96,8 +107,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -164,7 +175,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/objects/migrations/0003_auto__add_field_objectdb_db_destination.py b/src/objects/migrations/0003_auto__add_field_objectdb_db_destination.py index 121608c063..b35157b09a 100644 --- a/src/objects/migrations/0003_auto__add_field_objectdb_db_destination.py +++ b/src/objects/migrations/0003_auto__add_field_objectdb_db_destination.py @@ -6,6 +6,17 @@ from django.db import models from src.objects.models import ObjectDB from south import orm +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -41,8 +52,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -110,7 +121,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/objects/migrations/0004_rename_nick_to_objectnick.py b/src/objects/migrations/0004_rename_nick_to_objectnick.py index ec185397a7..2c51c6f0c6 100644 --- a/src/objects/migrations/0004_rename_nick_to_objectnick.py +++ b/src/objects/migrations/0004_rename_nick_to_objectnick.py @@ -4,6 +4,17 @@ from south.db import db from south.v2 import SchemaMigration from django.db import models, utils +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -47,8 +58,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -117,7 +128,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/objects/migrations/0005_add_object_default_locks.py b/src/objects/migrations/0005_add_object_default_locks.py index 0ae1bd3dd4..9be0da80d9 100644 --- a/src/objects/migrations/0005_add_object_default_locks.py +++ b/src/objects/migrations/0005_add_object_default_locks.py @@ -4,6 +4,17 @@ from south.db import db from south.v2 import DataMigration from django.db import models, utils +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(DataMigration): def forwards(self, orm): @@ -44,8 +55,8 @@ class Migration(DataMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -114,7 +125,7 @@ class Migration(DataMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/objects/migrations/0006_add_view_lock.py b/src/objects/migrations/0006_add_view_lock.py index 5de7d2be95..ed69c8a90b 100644 --- a/src/objects/migrations/0006_add_view_lock.py +++ b/src/objects/migrations/0006_add_view_lock.py @@ -4,6 +4,17 @@ from south.db import db from south.v2 import DataMigration from django.db import models, utils +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(DataMigration): def forwards(self, orm): @@ -42,8 +53,8 @@ class Migration(DataMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -112,7 +123,7 @@ class Migration(DataMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/objects/migrations/0007_auto__chg_field_objectdb_db_cmdset_storage__chg_field_objectdb_db_lock.py b/src/objects/migrations/0007_auto__chg_field_objectdb_db_cmdset_storage__chg_field_objectdb_db_lock.py index ba4cef59b3..685dc6a0ee 100644 --- a/src/objects/migrations/0007_auto__chg_field_objectdb_db_cmdset_storage__chg_field_objectdb_db_lock.py +++ b/src/objects/migrations/0007_auto__chg_field_objectdb_db_cmdset_storage__chg_field_objectdb_db_lock.py @@ -4,6 +4,17 @@ from south.db import db from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -50,8 +61,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -120,7 +131,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/objects/migrations/0008_auto.py b/src/objects/migrations/0008_auto.py index 0a6ab7995a..6ff2b3a649 100644 --- a/src/objects/migrations/0008_auto.py +++ b/src/objects/migrations/0008_auto.py @@ -4,6 +4,17 @@ from south.db import db from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -44,8 +55,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -114,7 +125,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/objects/migrations/0009_converting_attributes.py b/src/objects/migrations/0009_converting_attributes.py index 4368b592de..702e46349a 100644 --- a/src/objects/migrations/0009_converting_attributes.py +++ b/src/objects/migrations/0009_converting_attributes.py @@ -361,6 +361,17 @@ def from_attr(attr, datatuple): # all types of iterables return iter_id2db(data) +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(DataMigration): def forwards(self, orm): @@ -400,8 +411,8 @@ class Migration(DataMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -470,7 +481,7 @@ class Migration(DataMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/objects/migrations/0010_converting_attributes.py b/src/objects/migrations/0010_converting_attributes.py index 253c20e391..af7eebc8d6 100644 --- a/src/objects/migrations/0010_converting_attributes.py +++ b/src/objects/migrations/0010_converting_attributes.py @@ -269,6 +269,17 @@ def from_attr(attr, datatuple): # all types of iterables return iter_id2db(data) +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(DataMigration): def forwards(self, orm): @@ -301,8 +312,8 @@ class Migration(DataMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -371,7 +382,7 @@ class Migration(DataMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/objects/migrations/0011_typeclass_and_cmdset_to_new_api_default.py b/src/objects/migrations/0011_typeclass_and_cmdset_to_new_api_default.py index 9586ef8437..677520dedc 100644 --- a/src/objects/migrations/0011_typeclass_and_cmdset_to_new_api_default.py +++ b/src/objects/migrations/0011_typeclass_and_cmdset_to_new_api_default.py @@ -4,6 +4,17 @@ from south.db import db from south.v2 import DataMigration from django.db import models, utils +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(DataMigration): def forwards(self, orm): @@ -50,8 +61,8 @@ class Migration(DataMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -120,7 +131,7 @@ class Migration(DataMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/objects/migrations/0012_index_objattr_values.py b/src/objects/migrations/0012_index_objattr_values.py index af622d9e74..85b5ae3d5b 100644 --- a/src/objects/migrations/0012_index_objattr_values.py +++ b/src/objects/migrations/0012_index_objattr_values.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -31,8 +42,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -102,7 +113,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/objects/migrations/0013_revert_objattr_index.py b/src/objects/migrations/0013_revert_objattr_index.py index 2df3a2032c..88347fc62a 100644 --- a/src/objects/migrations/0013_revert_objattr_index.py +++ b/src/objects/migrations/0013_revert_objattr_index.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -30,8 +41,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -101,7 +112,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/objects/migrations/0014_auto__chg_field_objectdb_db_lock_storage.py b/src/objects/migrations/0014_auto__chg_field_objectdb_db_lock_storage.py index 8528242ef3..674545fc1b 100644 --- a/src/objects/migrations/0014_auto__chg_field_objectdb_db_lock_storage.py +++ b/src/objects/migrations/0014_auto__chg_field_objectdb_db_lock_storage.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -31,8 +42,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -102,7 +113,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/objects/migrations/0015_auto__chg_field_objattribute_db_lock_storage.py b/src/objects/migrations/0015_auto__chg_field_objattribute_db_lock_storage.py index c8a6597ff9..227f7ccd9e 100644 --- a/src/objects/migrations/0015_auto__chg_field_objattribute_db_lock_storage.py +++ b/src/objects/migrations/0015_auto__chg_field_objattribute_db_lock_storage.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -31,8 +42,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -102,7 +113,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/objects/migrations/0016_add_sessid.py b/src/objects/migrations/0016_add_sessid.py index ff9d42e6bf..87f9591826 100644 --- a/src/objects/migrations/0016_add_sessid.py +++ b/src/objects/migrations/0016_add_sessid.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -33,8 +44,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -104,7 +115,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/objects/migrations/0017_rename_default_cmdsets.py b/src/objects/migrations/0017_rename_default_cmdsets.py index adf98919b5..8412a4d03f 100644 --- a/src/objects/migrations/0017_rename_default_cmdsets.py +++ b/src/objects/migrations/0017_rename_default_cmdsets.py @@ -4,6 +4,17 @@ from south.db import db from south.v2 import DataMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(DataMigration): depends_on = (('players', '0014_add_attr__playable_characters'),) @@ -33,8 +44,8 @@ class Migration(DataMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -104,7 +115,7 @@ class Migration(DataMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/objects/migrations/0018_add_picklefield.py b/src/objects/migrations/0018_add_picklefield.py index f298420dc7..d44499fdd6 100644 --- a/src/objects/migrations/0018_add_picklefield.py +++ b/src/objects/migrations/0018_add_picklefield.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -33,8 +44,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -105,7 +116,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/objects/migrations/0019_convert_attrdata.py b/src/objects/migrations/0019_convert_attrdata.py index eebe9117f2..33cce76875 100644 --- a/src/objects/migrations/0019_convert_attrdata.py +++ b/src/objects/migrations/0019_convert_attrdata.py @@ -331,6 +331,17 @@ def to_attr(data): return ("simple", data) +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(DataMigration): def forwards(self, orm): @@ -435,8 +446,8 @@ class Migration(DataMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -507,7 +518,7 @@ class Migration(DataMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/objects/migrations/0020_remove_old_attr_value_field.py b/src/objects/migrations/0020_remove_old_attr_value_field.py index 477c7694ed..aca95071c9 100644 --- a/src/objects/migrations/0020_remove_old_attr_value_field.py +++ b/src/objects/migrations/0020_remove_old_attr_value_field.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -36,8 +47,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -107,7 +118,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/objects/migrations/0021_auto__del_objattribute.py b/src/objects/migrations/0021_auto__del_objattribute.py index b6377a22ea..2ac2ccb5c5 100644 --- a/src/objects/migrations/0021_auto__del_objattribute.py +++ b/src/objects/migrations/0021_auto__del_objattribute.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -50,8 +61,8 @@ class Migration(SchemaMigration): u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - u'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -114,7 +125,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, u'typeclasses.attribute': { 'Meta': {'object_name': 'Attribute'}, diff --git a/src/players/migrations/0001_initial.py b/src/players/migrations/0001_initial.py index a865b555d8..82af0ca229 100644 --- a/src/players/migrations/0001_initial.py +++ b/src/players/migrations/0001_initial.py @@ -4,6 +4,17 @@ from south.db import db from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): depends_on = ( @@ -32,7 +43,7 @@ class Migration(SchemaMigration): ('db_date_created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), ('db_permissions', self.gf('django.db.models.fields.CharField')(max_length=512, blank=True)), ('db_lock_storage', self.gf('django.db.models.fields.TextField')(blank=True)), - ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], unique=True)), + ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm[user_orm_label], unique=True)), ('db_obj', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['objects.ObjectDB'], null=True)), )) db.send_create_signal('players', ['PlayerDB']) @@ -64,8 +75,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -119,7 +130,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/players/migrations/0002_auto__del_field_playerattribute_db_mode.py b/src/players/migrations/0002_auto__del_field_playerattribute_db_mode.py index e7872bf7ed..1fecfe6d40 100644 --- a/src/players/migrations/0002_auto__del_field_playerattribute_db_mode.py +++ b/src/players/migrations/0002_auto__del_field_playerattribute_db_mode.py @@ -398,6 +398,17 @@ def from_attr(datatuple): elif typ == 'iter': # all types of iterables return iter_id2db(data) +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -447,8 +458,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -501,7 +512,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/players/migrations/0003_auto__add_field_playerdb_db_cmdset_storage.py b/src/players/migrations/0003_auto__add_field_playerdb_db_cmdset_storage.py index 3169188d57..bef24f62ac 100644 --- a/src/players/migrations/0003_auto__add_field_playerdb_db_cmdset_storage.py +++ b/src/players/migrations/0003_auto__add_field_playerdb_db_cmdset_storage.py @@ -4,6 +4,17 @@ from south.db import db from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -32,8 +43,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -88,7 +99,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) } } diff --git a/src/players/migrations/0004_auto__add_playernick__add_unique_playernick_db_nick_db_type_db_obj.py b/src/players/migrations/0004_auto__add_playernick__add_unique_playernick_db_nick_db_type_db_obj.py index c9f3bf9661..b2754d55fc 100644 --- a/src/players/migrations/0004_auto__add_playernick__add_unique_playernick_db_nick_db_type_db_obj.py +++ b/src/players/migrations/0004_auto__add_playernick__add_unique_playernick_db_nick_db_type_db_obj.py @@ -4,6 +4,17 @@ from south.db import db from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -45,8 +56,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -101,7 +112,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'players.playernick': { 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, diff --git a/src/players/migrations/0005_adding_player_cmdset.py b/src/players/migrations/0005_adding_player_cmdset.py index e417132e06..ba198f4e33 100644 --- a/src/players/migrations/0005_adding_player_cmdset.py +++ b/src/players/migrations/0005_adding_player_cmdset.py @@ -6,6 +6,17 @@ from django.db import models, utils from django.conf import settings +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(DataMigration): def forwards(self, orm): @@ -37,8 +48,8 @@ class Migration(DataMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -93,7 +104,7 @@ class Migration(DataMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'players.playernick': { 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, diff --git a/src/players/migrations/0006_auto__chg_field_playerdb_db_cmdset_storage__chg_field_playerdb_db_lock.py b/src/players/migrations/0006_auto__chg_field_playerdb_db_cmdset_storage__chg_field_playerdb_db_lock.py index 6c5b35fd1c..e7f2574d3e 100644 --- a/src/players/migrations/0006_auto__chg_field_playerdb_db_cmdset_storage__chg_field_playerdb_db_lock.py +++ b/src/players/migrations/0006_auto__chg_field_playerdb_db_cmdset_storage__chg_field_playerdb_db_lock.py @@ -4,6 +4,17 @@ from south.db import db from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -50,8 +61,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -106,7 +117,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'players.playernick': { 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, diff --git a/src/players/migrations/0007_auto.py b/src/players/migrations/0007_auto.py index 7080892483..9d5f4922bc 100644 --- a/src/players/migrations/0007_auto.py +++ b/src/players/migrations/0007_auto.py @@ -4,6 +4,17 @@ from south.db import db from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -38,8 +49,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -94,7 +105,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'players.playernick': { 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, diff --git a/src/players/migrations/0008_converting_attributes.py b/src/players/migrations/0008_converting_attributes.py index a970b07e26..5c86fb962e 100644 --- a/src/players/migrations/0008_converting_attributes.py +++ b/src/players/migrations/0008_converting_attributes.py @@ -365,6 +365,17 @@ def from_attr(attr, datatuple): return iter_id2db(data) +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(DataMigration): def forwards(self, orm): @@ -403,8 +414,8 @@ class Migration(DataMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -459,7 +470,7 @@ class Migration(DataMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'players.playernick': { 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, diff --git a/src/players/migrations/0009_converting_attributes.py b/src/players/migrations/0009_converting_attributes.py index fbb4c4bd68..b978094950 100644 --- a/src/players/migrations/0009_converting_attributes.py +++ b/src/players/migrations/0009_converting_attributes.py @@ -254,6 +254,17 @@ def from_attr(attr, datatuple): return iter_id2db(data) +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(DataMigration): def forwards(self, orm): @@ -286,8 +297,8 @@ class Migration(DataMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -342,7 +353,7 @@ class Migration(DataMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'players.playernick': { 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, diff --git a/src/players/migrations/0010_typeclass_and_cmdset_to_new_api_default.py b/src/players/migrations/0010_typeclass_and_cmdset_to_new_api_default.py index 208ecef3a8..78528b7d54 100644 --- a/src/players/migrations/0010_typeclass_and_cmdset_to_new_api_default.py +++ b/src/players/migrations/0010_typeclass_and_cmdset_to_new_api_default.py @@ -4,6 +4,17 @@ from south.db import db from south.v2 import DataMigration from django.db import models, utils +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(DataMigration): def forwards(self, orm): @@ -38,8 +49,8 @@ class Migration(DataMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -94,7 +105,7 @@ class Migration(DataMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'players.playernick': { 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, diff --git a/src/players/migrations/0011_addin_is_connected_field.py b/src/players/migrations/0011_addin_is_connected_field.py index 4489d89ec9..140a3e8918 100644 --- a/src/players/migrations/0011_addin_is_connected_field.py +++ b/src/players/migrations/0011_addin_is_connected_field.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -33,8 +44,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -90,7 +101,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'players.playernick': { 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, diff --git a/src/players/migrations/0012_auto__chg_field_playerdb_db_lock_storage.py b/src/players/migrations/0012_auto__chg_field_playerdb_db_lock_storage.py index 4e3534e575..72043d5ca1 100644 --- a/src/players/migrations/0012_auto__chg_field_playerdb_db_lock_storage.py +++ b/src/players/migrations/0012_auto__chg_field_playerdb_db_lock_storage.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -31,8 +42,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -88,7 +99,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'players.playernick': { 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, diff --git a/src/players/migrations/0013_auto__chg_field_playerattribute_db_lock_storage.py b/src/players/migrations/0013_auto__chg_field_playerattribute_db_lock_storage.py index a3e25da8a2..65564d956d 100644 --- a/src/players/migrations/0013_auto__chg_field_playerattribute_db_lock_storage.py +++ b/src/players/migrations/0013_auto__chg_field_playerattribute_db_lock_storage.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -31,8 +42,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -88,7 +99,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'players.playernick': { 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, diff --git a/src/players/migrations/0014_add_attr__playable_characters.py b/src/players/migrations/0014_add_attr__playable_characters.py index 5e43d416b2..472f9e2d3d 100644 --- a/src/players/migrations/0014_add_attr__playable_characters.py +++ b/src/players/migrations/0014_add_attr__playable_characters.py @@ -21,6 +21,17 @@ class PackedDBobject(object): return u"%s(#%s)" % (self.key, self.id) +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(DataMigration): def forwards(self, orm): @@ -76,8 +87,8 @@ class Migration(DataMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -142,7 +153,7 @@ class Migration(DataMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'players.playernick': { 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, diff --git a/src/players/migrations/0015_removing_obj.py b/src/players/migrations/0015_removing_obj.py index 4601ee25e5..7ec2f00483 100644 --- a/src/players/migrations/0015_removing_obj.py +++ b/src/players/migrations/0015_removing_obj.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -34,8 +45,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -92,7 +103,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'players.playernick': { 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, diff --git a/src/players/migrations/0016_rename_default_cmdsets.py b/src/players/migrations/0016_rename_default_cmdsets.py index d0fd40f9be..82ee447995 100644 --- a/src/players/migrations/0016_rename_default_cmdsets.py +++ b/src/players/migrations/0016_rename_default_cmdsets.py @@ -4,6 +4,17 @@ from south.db import db from south.v2 import DataMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(DataMigration): def forwards(self, orm): @@ -32,8 +43,8 @@ class Migration(DataMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -74,7 +85,7 @@ class Migration(DataMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'players.playernick': { 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, diff --git a/src/players/migrations/0017_add_picklefield.py b/src/players/migrations/0017_add_picklefield.py index 177dca1bcc..550768d4cb 100644 --- a/src/players/migrations/0017_add_picklefield.py +++ b/src/players/migrations/0017_add_picklefield.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -33,8 +44,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -76,7 +87,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'players.playernick': { 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, diff --git a/src/players/migrations/0018_convert_attrdata.py b/src/players/migrations/0018_convert_attrdata.py index 343bd030a2..bd7e77e935 100644 --- a/src/players/migrations/0018_convert_attrdata.py +++ b/src/players/migrations/0018_convert_attrdata.py @@ -269,6 +269,17 @@ class PackedSet(set): +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(DataMigration): depends_on = ( ("objects", "0018_add_picklefield"), @@ -371,8 +382,8 @@ class Migration(DataMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -429,7 +440,7 @@ class Migration(DataMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'players.playernick': { 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, diff --git a/src/players/migrations/0019_remove_old_attr_value_field.py b/src/players/migrations/0019_remove_old_attr_value_field.py index db5472d449..5c3483f68b 100644 --- a/src/players/migrations/0019_remove_old_attr_value_field.py +++ b/src/players/migrations/0019_remove_old_attr_value_field.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -34,8 +45,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -76,7 +87,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'players.playernick': { 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, diff --git a/src/players/migrations/0020_auto__del_playerattribute.py b/src/players/migrations/0020_auto__del_playerattribute.py index 6f7b456cf6..4c2975df53 100644 --- a/src/players/migrations/0020_auto__del_playerattribute.py +++ b/src/players/migrations/0020_auto__del_playerattribute.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -50,8 +61,8 @@ class Migration(SchemaMigration): u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - u'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -84,7 +95,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, u'players.playernick': { 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, diff --git a/src/players/migrations/0021_add_playerdbtmp.py b/src/players/migrations/0021_add_playerdbtmp.py index 85e503b327..64624eb99a 100644 --- a/src/players/migrations/0021_add_playerdbtmp.py +++ b/src/players/migrations/0021_add_playerdbtmp.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models, connection +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -12,6 +23,7 @@ class Migration(SchemaMigration): if "auth_user" in connection.introspection.table_names(): # auth_user exists ffrom before. Use that as a base. db.rename_table('auth_user', 'players_playerdbtmp') + else: # from-scratch creation; no auth_user table available. Create vanilla User table db.create_table(u'players_playerdbtmp', ( @@ -45,16 +57,6 @@ class Migration(SchemaMigration): )) db.create_unique(u'players_playerdbtmp_user_permissions', ['playerdbtmp_id', 'permission_id']) - # Adding field 'PlayerDB.db_is_connected' - db.add_column(u'players_playerdb', 'db_is_connected', - self.gf('django.db.models.fields.BooleanField')(default=False), - keep_default=False) - - # Adding field 'PlayerDB.db_cmdset_storage' - db.add_column(u'players_playerdb', 'db_cmdset_storage', - self.gf('django.db.models.fields.CharField')(max_length=255, null=True), - keep_default=False) - # add Evennia-specific columns db.add_column('players_playerdbtmp', 'db_key', self.gf('django.db.models.fields.CharField')(max_length=255, db_index=True, null=True)) db.add_column('players_playerdbtmp', 'db_typeclass_path', self.gf('django.db.models.fields.CharField')(max_length=255, null=True)) @@ -82,8 +84,8 @@ class Migration(SchemaMigration): u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - u'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -116,31 +118,9 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, u'players.playerdbtmp': { - 'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDBtmp'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), - 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), - 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), - 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), - 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) }, u'typeclasses.attribute': { 'Meta': {'object_name': 'Attribute'}, diff --git a/src/players/migrations/0022_copy_user_profile_to_tmp.py b/src/players/migrations/0022_copy_user_profile_to_tmp.py index 2ea41dc715..302ccd1934 100644 --- a/src/players/migrations/0022_copy_user_profile_to_tmp.py +++ b/src/players/migrations/0022_copy_user_profile_to_tmp.py @@ -4,6 +4,17 @@ from south.db import db from south.v2 import DataMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(DataMigration): def forwards(self, orm): @@ -40,8 +51,8 @@ class Migration(DataMigration): u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - u'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -74,7 +85,7 @@ class Migration(DataMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, u'players.playerdbtmp': { 'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDBtmp'}, diff --git a/src/players/migrations/0023_delete_old_profile.py b/src/players/migrations/0023_delete_old_profile.py index 5f84edeaf6..da7372c67a 100644 --- a/src/players/migrations/0023_delete_old_profile.py +++ b/src/players/migrations/0023_delete_old_profile.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -27,8 +38,8 @@ class Migration(SchemaMigration): u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - u'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -61,7 +72,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, u'players.playerdbtmp': { 'Meta': {'ordering': "['-db_date_created', 'id', 'db_typeclass_path', 'db_key']", 'object_name': 'PlayerDBtmp'}, diff --git a/src/scripts/migrations/0001_initial.py b/src/scripts/migrations/0001_initial.py index 3998ef1ae3..e5a78a9b79 100644 --- a/src/scripts/migrations/0001_initial.py +++ b/src/scripts/migrations/0001_initial.py @@ -4,7 +4,21 @@ from south.db import db from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): + + depends_on = ( + ('objects', '0001_initial'),) def forwards(self, orm): @@ -62,8 +76,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -107,7 +121,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'scripts.scriptattribute': { 'Meta': {'object_name': 'ScriptAttribute'}, diff --git a/src/scripts/migrations/0002_auto__del_field_scriptattribute_db_mode.py b/src/scripts/migrations/0002_auto__del_field_scriptattribute_db_mode.py index 495be061b8..d2822e03f4 100644 --- a/src/scripts/migrations/0002_auto__del_field_scriptattribute_db_mode.py +++ b/src/scripts/migrations/0002_auto__del_field_scriptattribute_db_mode.py @@ -60,6 +60,17 @@ class PackedDBobject(object): return "%s(#%s)" % (self.key, self.id) def __unicode__(self): return u"%s(#%s)" % (self.key, self.id) +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -107,8 +118,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -152,7 +163,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'scripts.scriptattribute': { 'Meta': {'object_name': 'ScriptAttribute'}, diff --git a/src/scripts/migrations/0003_auto__chg_field_scriptdb_db_lock_storage__chg_field_scriptdb_db_permis.py b/src/scripts/migrations/0003_auto__chg_field_scriptdb_db_lock_storage__chg_field_scriptdb_db_permis.py index 6a62b983d8..e34c0f3223 100644 --- a/src/scripts/migrations/0003_auto__chg_field_scriptdb_db_lock_storage__chg_field_scriptdb_db_permis.py +++ b/src/scripts/migrations/0003_auto__chg_field_scriptdb_db_lock_storage__chg_field_scriptdb_db_permis.py @@ -4,6 +4,17 @@ from south.db import db from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -44,8 +55,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -91,7 +102,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'scripts.scriptattribute': { 'Meta': {'object_name': 'ScriptAttribute'}, diff --git a/src/scripts/migrations/0004_auto.py b/src/scripts/migrations/0004_auto.py index d68addaad3..4f6b80e46e 100644 --- a/src/scripts/migrations/0004_auto.py +++ b/src/scripts/migrations/0004_auto.py @@ -4,6 +4,17 @@ from south.db import db from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -38,8 +49,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -85,7 +96,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'scripts.scriptattribute': { 'Meta': {'object_name': 'ScriptAttribute'}, diff --git a/src/scripts/migrations/0005_converting_attributes.py b/src/scripts/migrations/0005_converting_attributes.py index 1f37695772..cfeb9cecee 100644 --- a/src/scripts/migrations/0005_converting_attributes.py +++ b/src/scripts/migrations/0005_converting_attributes.py @@ -364,6 +364,17 @@ def from_attr(attr, datatuple): # all types of iterables return iter_id2db(data) +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(DataMigration): def forwards(self, orm): @@ -401,8 +412,8 @@ class Migration(DataMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -448,7 +459,7 @@ class Migration(DataMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'scripts.scriptattribute': { 'Meta': {'object_name': 'ScriptAttribute'}, diff --git a/src/scripts/migrations/0006_converting_attributes.py b/src/scripts/migrations/0006_converting_attributes.py index f236af33f2..b6bc873a69 100644 --- a/src/scripts/migrations/0006_converting_attributes.py +++ b/src/scripts/migrations/0006_converting_attributes.py @@ -254,6 +254,17 @@ def from_attr(attr, datatuple): # all types of iterables return iter_id2db(data) +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(DataMigration): def forwards(self, orm): @@ -285,8 +296,8 @@ class Migration(DataMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -332,7 +343,7 @@ class Migration(DataMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'scripts.scriptattribute': { 'Meta': {'object_name': 'ScriptAttribute'}, diff --git a/src/scripts/migrations/0007_typeclass_to_new_api_default.py b/src/scripts/migrations/0007_typeclass_to_new_api_default.py index d1f0d94699..faa1461701 100644 --- a/src/scripts/migrations/0007_typeclass_to_new_api_default.py +++ b/src/scripts/migrations/0007_typeclass_to_new_api_default.py @@ -4,6 +4,17 @@ from south.db import db from south.v2 import DataMigration from django.db import models, utils +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(DataMigration): def forwards(self, orm): @@ -39,8 +50,8 @@ class Migration(DataMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -86,7 +97,7 @@ class Migration(DataMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'scripts.scriptattribute': { 'Meta': {'object_name': 'ScriptAttribute'}, diff --git a/src/scripts/migrations/0008_auto__chg_field_scriptdb_db_lock_storage.py b/src/scripts/migrations/0008_auto__chg_field_scriptdb_db_lock_storage.py index 8e9dde21d9..261b498b7b 100644 --- a/src/scripts/migrations/0008_auto__chg_field_scriptdb_db_lock_storage.py +++ b/src/scripts/migrations/0008_auto__chg_field_scriptdb_db_lock_storage.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -31,8 +42,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -79,7 +90,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'scripts.scriptattribute': { 'Meta': {'object_name': 'ScriptAttribute'}, diff --git a/src/scripts/migrations/0009_auto__chg_field_scriptattribute_db_lock_storage.py b/src/scripts/migrations/0009_auto__chg_field_scriptattribute_db_lock_storage.py index 35b04fcb12..46000571e0 100644 --- a/src/scripts/migrations/0009_auto__chg_field_scriptattribute_db_lock_storage.py +++ b/src/scripts/migrations/0009_auto__chg_field_scriptattribute_db_lock_storage.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -31,8 +42,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -79,7 +90,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'scripts.scriptattribute': { 'Meta': {'object_name': 'ScriptAttribute'}, diff --git a/src/scripts/migrations/0010_add_picklefield.py b/src/scripts/migrations/0010_add_picklefield.py index 85f126aead..174e25419c 100644 --- a/src/scripts/migrations/0010_add_picklefield.py +++ b/src/scripts/migrations/0010_add_picklefield.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -33,8 +44,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -81,7 +92,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'scripts.scriptattribute': { 'Meta': {'object_name': 'ScriptAttribute'}, diff --git a/src/scripts/migrations/0011_convert_attrdata.py b/src/scripts/migrations/0011_convert_attrdata.py index 0c09d47796..373467a495 100644 --- a/src/scripts/migrations/0011_convert_attrdata.py +++ b/src/scripts/migrations/0011_convert_attrdata.py @@ -332,6 +332,17 @@ def to_attr(data): return ("simple", data) +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(DataMigration): depends_on = ( @@ -436,8 +447,8 @@ class Migration(DataMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -484,7 +495,7 @@ class Migration(DataMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'scripts.scriptattribute': { 'Meta': {'object_name': 'ScriptAttribute'}, diff --git a/src/scripts/migrations/0012_remove_old_attr_value_field.py b/src/scripts/migrations/0012_remove_old_attr_value_field.py index a9064d20ad..3d8a33a90e 100644 --- a/src/scripts/migrations/0012_remove_old_attr_value_field.py +++ b/src/scripts/migrations/0012_remove_old_attr_value_field.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -33,8 +44,8 @@ class Migration(SchemaMigration): 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - 'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -81,7 +92,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, 'scripts.scriptattribute': { 'Meta': {'object_name': 'ScriptAttribute'}, diff --git a/src/scripts/migrations/0013_auto__del_scriptattribute.py b/src/scripts/migrations/0013_auto__del_scriptattribute.py index 2b74eddb9d..0891184daf 100644 --- a/src/scripts/migrations/0013_auto__del_scriptattribute.py +++ b/src/scripts/migrations/0013_auto__del_scriptattribute.py @@ -5,6 +5,17 @@ from south.v2 import SchemaMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(SchemaMigration): def forwards(self, orm): @@ -50,8 +61,8 @@ class Migration(SchemaMigration): u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - u'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -100,7 +111,7 @@ class Migration(SchemaMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, u'scripts.scriptdb': { 'Meta': {'object_name': 'ScriptDB'}, diff --git a/src/server/migrations/0002_fix_config_value.py b/src/server/migrations/0002_fix_config_value.py index 129b08e752..a5da54880d 100644 --- a/src/server/migrations/0002_fix_config_value.py +++ b/src/server/migrations/0002_fix_config_value.py @@ -27,6 +27,8 @@ class Migration(DataMigration): conf.save() except utils.DatabaseError: # this will happen if we start the db from scratch (in which case this migration fix is not needed) + db.commit_transaction() + db.start_transaction() pass diff --git a/src/typeclasses/migrations/0002_resave_attrs.py b/src/typeclasses/migrations/0002_resave_attrs.py index 0fa7792857..355d1cd2b9 100644 --- a/src/typeclasses/migrations/0002_resave_attrs.py +++ b/src/typeclasses/migrations/0002_resave_attrs.py @@ -4,6 +4,17 @@ from south.db import db from south.v2 import DataMigration from django.db import models +try: + from django.contrib.auth import get_user_model +except ImportError: # django < 1.5 + from django.contrib.auth.models import User +else: + User = get_user_model() + +user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name) +user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name) +user_ptr_name = '%s_ptr' % User._meta.object_name.lower() + class Migration(DataMigration): depends_on = (('server', '0004_store_all_attrs'), ('objects', '0021_auto__del_objattribute'), @@ -65,8 +76,8 @@ class Migration(DataMigration): u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, - u'auth.user': { - 'Meta': {'object_name': 'User'}, + user_model_label: { + 'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table}, 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), @@ -153,7 +164,7 @@ class Migration(DataMigration): 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['auth.User']", 'unique': 'True'}) + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'}) }, u'players.playernick': { 'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'}, From 8ba5be0b2d074ae3763476473773e33d131749ea Mon Sep 17 00:00:00 2001 From: Kelketek Date: Sat, 20 Jul 2013 16:32:24 -0500 Subject: [PATCH 42/49] Adjusted migrations to more properly handled dependent tables. --- .../migrations/0021_add_playerdbtmp.py | 4 + .../migrations/0024_rename_tmp_to_player.py | 9 +- .../migrations/0027_permissions_and_groups.py | 93 ------------------- 3 files changed, 12 insertions(+), 94 deletions(-) delete mode 100644 src/players/migrations/0027_permissions_and_groups.py diff --git a/src/players/migrations/0021_add_playerdbtmp.py b/src/players/migrations/0021_add_playerdbtmp.py index 64624eb99a..dad0b00de0 100644 --- a/src/players/migrations/0021_add_playerdbtmp.py +++ b/src/players/migrations/0021_add_playerdbtmp.py @@ -23,6 +23,10 @@ class Migration(SchemaMigration): if "auth_user" in connection.introspection.table_names(): # auth_user exists ffrom before. Use that as a base. db.rename_table('auth_user', 'players_playerdbtmp') + db.rename_table('auth_user_groups', 'players_playerdbtmp_groups') + db.rename_table('auth_user_user_permissions', 'player_playerdbtmp_user_permissions') + db.rename_column('players_playerdbtmp_groups', 'user_id', 'playerdbtmp_id') + db.rename_column('players_playerdbtmp_user_permissions', 'user_id', 'playerdbtmp_id') else: # from-scratch creation; no auth_user table available. Create vanilla User table diff --git a/src/players/migrations/0024_rename_tmp_to_player.py b/src/players/migrations/0024_rename_tmp_to_player.py index f89371f9ef..098ac9ae3e 100644 --- a/src/players/migrations/0024_rename_tmp_to_player.py +++ b/src/players/migrations/0024_rename_tmp_to_player.py @@ -9,9 +9,16 @@ class Migration(SchemaMigration): def forwards(self, orm): db.rename_table('players_playerdbtmp', 'players_playerdb') + db.rename_table('players_playerdbtmp_groups', 'players_playerdb_groups') + db.rename_column('players_playerdb_groups', 'playerdbtmp_id', 'playerdb_id') + db.rename_table('players_playerdbtmp_user_permissions', 'players_playerdb_user_permissions') + db.rename_column('players_playerdb_user_permissions', 'playerdbtmp_id', 'playerdb_id') def backwards(self, orm): - raise RuntimeError("Cannot revert this migration.") + db.rename_table('players_playerdb_groups', 'players_playerdbtmp_groups') + db.rename_column('players_playerdbtmp_groups', 'playerdb_id', 'playerdbtmp_id') + db.rename_table('players_playerdb_user_permissions', 'players_playerdbtmp_user_permissions') + db.rename_column('players_playerdbtmp_user_permissions', 'playerdb_id', 'playerdbtmp_id') models = { u'auth.group': { diff --git a/src/players/migrations/0027_permissions_and_groups.py b/src/players/migrations/0027_permissions_and_groups.py deleted file mode 100644 index 297bacd3d2..0000000000 --- a/src/players/migrations/0027_permissions_and_groups.py +++ /dev/null @@ -1,93 +0,0 @@ -# -*- coding: utf-8 -*- -import datetime -from south.db import db -from south.v2 import SchemaMigration -from django.db import models - - -class Migration(SchemaMigration): - - def forwards(self, orm): - db.rename_table('players_playerdbtmp_groups', 'players_playerdb_groups') - db.rename_column('players_playerdb_groups', 'playerdbtmp_id', 'playerdb_id') - db.rename_table('players_playerdbtmp_user_permissions', 'players_playerdb_user_permissions') - db.rename_column('players_playerdb_user_permissions', 'playerdbtmp_id', 'playerdb_id') - - def backwards(self, orm): - db.rename_table('players_playerdb_groups', 'players_playerdbtmp_groups') - db.rename_column('players_playerdbtmp_groups', 'playerdb_id', 'playerdbtmp_id') - db.rename_table('players_playerdb_user_permissions', 'players_playerdbtmp_user_permissions') - db.rename_column('players_playerdbtmp_user_permissions', 'playerdb_id', 'playerdbtmp_id') - - models = { - u'auth.group': { - 'Meta': {'object_name': 'Group'}, - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), - 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) - }, - u'auth.permission': { - 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, - 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) - }, - u'contenttypes.contenttype': { - 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, - 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), - 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) - }, - u'players.playerdb': { - 'Meta': {'object_name': 'PlayerDB'}, - 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}), - 'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), - 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), - 'db_liteattributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.LiteAttribute']", 'null': 'True', 'symmetrical': 'False'}), - 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), - 'db_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Tag']", 'null': 'True', 'symmetrical': 'False'}), - 'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), - 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), - 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), - 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), - 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), - 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), - 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), - 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), - 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), - 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) - }, - u'typeclasses.attribute': { - 'Meta': {'object_name': 'Attribute'}, - 'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), - 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}), - 'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}), - 'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) - }, - u'typeclasses.liteattribute': { - 'Meta': {'object_name': 'LiteAttribute', 'index_together': "(('db_key', 'db_category'),)"}, - 'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}), - 'db_data': ('django.db.models.fields.TextField', [], {}), - 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) - }, - u'typeclasses.tag': { - 'Meta': {'unique_together': "(('db_key', 'db_category'),)", 'object_name': 'Tag', 'index_together': "(('db_key', 'db_category'),)"}, - 'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}), - 'db_data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), - 'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}), - u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) - } - } - - complete_apps = ['players'] From d861cc5e8b7e31a04b6dc265e8453e63883c3826 Mon Sep 17 00:00:00 2001 From: Kelketek Date: Sat, 20 Jul 2013 16:54:11 -0500 Subject: [PATCH 43/49] Fixed a typo in that last one. And this time, it succeeded! --- src/players/migrations/0021_add_playerdbtmp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/players/migrations/0021_add_playerdbtmp.py b/src/players/migrations/0021_add_playerdbtmp.py index dad0b00de0..08489a859b 100644 --- a/src/players/migrations/0021_add_playerdbtmp.py +++ b/src/players/migrations/0021_add_playerdbtmp.py @@ -24,7 +24,7 @@ class Migration(SchemaMigration): # auth_user exists ffrom before. Use that as a base. db.rename_table('auth_user', 'players_playerdbtmp') db.rename_table('auth_user_groups', 'players_playerdbtmp_groups') - db.rename_table('auth_user_user_permissions', 'player_playerdbtmp_user_permissions') + db.rename_table('auth_user_user_permissions', 'players_playerdbtmp_user_permissions') db.rename_column('players_playerdbtmp_groups', 'user_id', 'playerdbtmp_id') db.rename_column('players_playerdbtmp_user_permissions', 'user_id', 'playerdbtmp_id') From 699f86273b23c0a3c82c99911bec9112908877b4 Mon Sep 17 00:00:00 2001 From: Kelketek Date: Sat, 20 Jul 2013 19:36:32 -0500 Subject: [PATCH 44/49] Customized Reverse Proxy to send along host header from client. --- src/server/portal/portal.py | 4 +++- src/server/webserver.py | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/server/portal/portal.py b/src/server/portal/portal.py index be5b7c1f4b..f35ae4e6db 100644 --- a/src/server/portal/portal.py +++ b/src/server/portal/portal.py @@ -9,6 +9,8 @@ by game/evennia.py). """ import sys import os +from src.server.webserver import EvenniaReverseProxyResource + if os.name == 'nt': # For Windows batchfile we need an extra path insertion here. sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname( @@ -256,7 +258,7 @@ if WEBSERVER_ENABLED: ifacestr = "-%s" % interface for proxyport, serverport in WEBSERVER_PORTS: pstring = "%s:%s<->%s" % (ifacestr, proxyport, serverport) - web_root = proxy.ReverseProxyResource('127.0.0.1', serverport, '') + web_root = EvenniaReverseProxyResource('127.0.0.1', serverport, '') webclientstr = "" if WEBCLIENT_ENABLED: # create ajax client processes at /webclientdata diff --git a/src/server/webserver.py b/src/server/webserver.py index 9daf5d8b20..fdea83bb99 100644 --- a/src/server/webserver.py +++ b/src/server/webserver.py @@ -11,10 +11,13 @@ application. a great example/aid on how to do this.) """ +import urlparse +from urllib import quote as urlquote from twisted.web import resource, http -from twisted.python import threadpool from twisted.internet import reactor from twisted.application import service, internet +from twisted.web.proxy import ReverseProxyResource +from twisted.web.server import NOT_DONE_YET from twisted.web.wsgi import WSGIResource from django.core.handlers.wsgi import WSGIHandler @@ -44,6 +47,36 @@ class HTTPChannelWithXForwardedFor(http.HTTPChannel): http.HTTPFactory.protocol = HTTPChannelWithXForwardedFor +class EvenniaReverseProxyResource(ReverseProxyResource): + def getChild(self, path, request): + """ + Create and return a proxy resource with the same proxy configuration + as this one, except that its path also contains the segment given by + C{path} at the end. + """ + return EvenniaReverseProxyResource( + self.host, self.port, self.path + '/' + urlquote(path, safe=""), + self.reactor) + + + def render(self, request): + """ + Render a request by forwarding it to the proxied server. + """ + # RFC 2616 tells us that we can omit the port if it's the default port, + # but we have to provide it otherwise + request.content.seek(0, 0) + qs = urlparse.urlparse(request.uri)[4] + if qs: + rest = self.path + '?' + qs + else: + rest = self.path + clientFactory = self.proxyClientFactoryClass( + request.method, rest, request.clientproto, + request.getAllHeaders(), request.content.read(), request) + self.reactor.connectTCP(self.host, self.port, clientFactory) + return NOT_DONE_YET + # # Website server resource # From 427dcc39855f8704880182de54205dec1ef9dade Mon Sep 17 00:00:00 2001 From: Kelketek Date: Sun, 21 Jul 2013 09:44:34 -0500 Subject: [PATCH 45/49] Optimized Scripts admin page. Fixed related name for objects on attributes. Repaired search. Removed some backwards compatible parts of picklefield since we aren't supporting version older than 1.5 and they were obscuring the true cause of some issues. --- src/objects/manager.py | 21 +++++++++++---------- src/scripts/admin.py | 1 + src/typeclasses/models.py | 5 +++-- src/utils/picklefield.py | 10 ++-------- 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/objects/manager.py b/src/objects/manager.py index ea0d3ebf8a..fae02e6a00 100644 --- a/src/objects/manager.py +++ b/src/objects/manager.py @@ -1,6 +1,7 @@ """ Custom manager for Objects. """ +from itertools import chain from django.db.models import Q from django.conf import settings from django.db.models.fields import exceptions @@ -117,16 +118,16 @@ class ObjectManager(TypedObjectManager): #q = self.filter(cand_restriction & type_restriction & Q(objattribute__db_key=attribute_name) & Q(objattribute__db_value=attribute_value)) #return list(q) - #if isinstance(attribute_value, (basestring, int, float, bool, long)): - return self.filter(cand_restriction & type_restriction & Q(db_attributes__db_key=attribute_name, db_attributes__db_value=attribute_value)) - #else: - # # We have to loop for safety since the referenced lookup gives deepcopy error if attribute value is an object. - # global _ATTR - # if not _ATTR: - # from src.typeclasses.models import Attribute as _ATTR - # cands = list(self.filter(cand_restriction & type_restriction & Q(objattribute__db_key=attribute_name))) - # return [_ATTR. - # return [_GA(attr, "db_obj") for attr in _OBJATTR.objects.filter(db_obj__in=cands, db_value=attribute_value)] + if isinstance(attribute_value, (basestring, int, float, bool, long)): + return self.filter(cand_restriction & type_restriction & Q(db_attributes__db_key=attribute_name, db_attributes__db_value=attribute_value)) + else: + # We have to loop for safety since the referenced lookup gives deepcopy error if attribute value is an object. + global _ATTR + if not _ATTR: + from src.typeclasses.models import Attribute as _ATTR + cands = list(self.filter(cand_restriction & type_restriction & Q(db_attributes__db_key=attribute_name))) + results = [attr.db_objects.all() for attr in _ATTR.objects.filter(db_objects__in=cands, db_value=attribute_value)] + return chain(*results) @returns_typeclass_list def get_objs_with_db_property(self, property_name, candidates=None): diff --git a/src/scripts/admin.py b/src/scripts/admin.py index da8a492ecd..89e1413e76 100644 --- a/src/scripts/admin.py +++ b/src/scripts/admin.py @@ -21,6 +21,7 @@ class ScriptDBAdmin(admin.ModelAdmin): save_as = True save_on_top = True list_select_related = True + raw_id_fields = ('db_obj',) fieldsets = ( (None, { diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index ea99c0bb11..e3ad91f99b 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -596,7 +596,8 @@ class TypedObject(SharedMemoryModel): help_text="locks limit access to an entity. A lock is defined as a 'lock string' on the form 'type:lockfunctions', defining what functionality is locked and how to determine access. Not defining a lock means no access is granted.") # many2many relationships db_attributes = models.ManyToManyField(Attribute, null=True, - help_text='attributes on this object. An attribute can hold any pickle-able python object (see docs for special cases).') + help_text='attributes on this object. An attribute can hold any pickle-able python object (see docs for special cases).', + related_name='db_objects') db_liteattributes = models.ManyToManyField(LiteAttribute, null=True, help_text='liteattributes on this object. A LiteAttribute holds a key, a category and a string field for simple lookups.') db_tags = models.ManyToManyField(Tag, null=True, @@ -1158,7 +1159,7 @@ class TypedObject(SharedMemoryModel): attribute_name: (str) The attribute's name. default: What to return if no attribute is found - raise_exception (bool) - raise an eception if no object exists instead of returning default. + raise_exception (bool) - raise an exception if no object exists instead of returning default. """ attr_obj = get_attr_cache(self, attribute_name) if not attr_obj: diff --git a/src/utils/picklefield.py b/src/utils/picklefield.py index bcb513c819..dc33464ee3 100644 --- a/src/utils/picklefield.py +++ b/src/utils/picklefield.py @@ -217,14 +217,8 @@ class PickledObjectField(_get_subfield_superclass()): raise TypeError('Lookup type %s is not supported.' % lookup_type) # The Field model already calls get_db_prep_value before doing the # actual lookup, so all we need to do is limit the lookup types. - try: - return super(PickledObjectField, self).get_db_prep_lookup( - lookup_type, value, connection=connection, prepared=prepared) - except TypeError: - # Try not to break on older versions of Django, where the - # `connection` and `prepared` parameters are not available. - return super(PickledObjectField, self).get_db_prep_lookup( - lookup_type, value) + return super(PickledObjectField, self).get_db_prep_lookup( + lookup_type, value, connection=connection, prepared=prepared) # South support; see http://south.aeracode.org/docs/tutorial/part4.html#simple-inheritance From 08ee399ea2c83480bfd55f502347861ec76cc7ed Mon Sep 17 00:00:00 2001 From: Kelketek Date: Sun, 21 Jul 2013 14:18:36 -0500 Subject: [PATCH 46/49] Better way of doing that with less side effects. Thought it wasn't possible earlier because I misread something. --- src/objects/manager.py | 4 +--- src/typeclasses/models.py | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/objects/manager.py b/src/objects/manager.py index fae02e6a00..901d6fa7cd 100644 --- a/src/objects/manager.py +++ b/src/objects/manager.py @@ -115,8 +115,6 @@ class ObjectManager(TypedObjectManager): type_restriction = typeclasses and Q(db_typeclass_path__in=make_iter(typeclasses)) or Q() ## This doesn't work if attribute_value is an object. Workaround below - #q = self.filter(cand_restriction & type_restriction & Q(objattribute__db_key=attribute_name) & Q(objattribute__db_value=attribute_value)) - #return list(q) if isinstance(attribute_value, (basestring, int, float, bool, long)): return self.filter(cand_restriction & type_restriction & Q(db_attributes__db_key=attribute_name, db_attributes__db_value=attribute_value)) @@ -126,7 +124,7 @@ class ObjectManager(TypedObjectManager): if not _ATTR: from src.typeclasses.models import Attribute as _ATTR cands = list(self.filter(cand_restriction & type_restriction & Q(db_attributes__db_key=attribute_name))) - results = [attr.db_objects.all() for attr in _ATTR.objects.filter(db_objects__in=cands, db_value=attribute_value)] + results = [attr.objectdb_set.all() for attr in _ATTR.objects.filter(objectdb__in=cands, db_value=attribute_value)] return chain(*results) @returns_typeclass_list diff --git a/src/typeclasses/models.py b/src/typeclasses/models.py index e3ad91f99b..1d3c1daa28 100644 --- a/src/typeclasses/models.py +++ b/src/typeclasses/models.py @@ -596,8 +596,7 @@ class TypedObject(SharedMemoryModel): help_text="locks limit access to an entity. A lock is defined as a 'lock string' on the form 'type:lockfunctions', defining what functionality is locked and how to determine access. Not defining a lock means no access is granted.") # many2many relationships db_attributes = models.ManyToManyField(Attribute, null=True, - help_text='attributes on this object. An attribute can hold any pickle-able python object (see docs for special cases).', - related_name='db_objects') + help_text='attributes on this object. An attribute can hold any pickle-able python object (see docs for special cases).') db_liteattributes = models.ManyToManyField(LiteAttribute, null=True, help_text='liteattributes on this object. A LiteAttribute holds a key, a category and a string field for simple lookups.') db_tags = models.ManyToManyField(Tag, null=True, From 55c0e4030950f0fb12e4527657416a3cb60f1426 Mon Sep 17 00:00:00 2001 From: Kelketek Date: Sun, 21 Jul 2013 17:22:38 -0500 Subject: [PATCH 47/49] Fixed the tag migrations. Didn't need to fool with transactions after all. --- ...copy_nicks_to_liteattrs_aliases_to_tags.py | 46 ++++++------------- 1 file changed, 14 insertions(+), 32 deletions(-) diff --git a/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py b/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py index 5c6280f81c..80ae81d88c 100644 --- a/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py +++ b/src/typeclasses/migrations/0004_copy_nicks_to_liteattrs_aliases_to_tags.py @@ -4,10 +4,12 @@ from south.db import db from south.v2 import DataMigration from django.db import models, IntegrityError + class Migration(DataMigration): depends_on = (("objects", "0022_add_db_liteattributes_db_tags"), ("players", "0025_auto__add_db_liteattributes_db_tags")) + def forwards(self, orm): "Write your forwards methods here." # Note: Don't use "from appname.models import ModelName". @@ -16,47 +18,27 @@ class Migration(DataMigration): # Each alias and nick is its own case. By default, this function starts # in a transaction, so we'll close that and make our own transactions. - db.commit_transaction() for alias in orm['objects.Alias'].objects.all(): # convert all Aliases to tags try: - db.start_transaction() + tag = orm.Tag.objects.get(db_key=alias.db_key, db_category="object_alias") + except orm.Tag.DoesNotExist: tag = orm.Tag(db_key=alias.db_key, db_category="object_alias", db_data=None) tag.save() - obj = alias.db_obj - obj.db_tags.add(tag) - db.commit_transaction() - except IntegrityError: - db.commit_transaction() - print "Tag already exists: %s for %s" % (alias.db_key, alias.db_obj.db_key) + obj = alias.db_obj + obj.db_tags.add(tag) # convert all nicks to LiteAttrs for nick in orm['objects.ObjectNick'].objects.all(): - try: - db.start_transaction() - lattr = orm.LiteAttribute(db_key=nick.db_nick, db_category="object_nick_%s" % nick.db_type, db_data=nick.db_real) - lattr.save() - obj = nick.db_obj - obj.db_liteattributes.add(lattr) - db.commit_transaction() - except IntegrityError: - db.commit_transaction() - print "Nick already exists: %s for %s" % (nick.db_nick, nick.db_obj.db_key) + lattr = orm.LiteAttribute(db_key=nick.db_nick, db_category="object_nick_%s" % nick.db_type, db_data=nick.db_real) + lattr.save() + obj = nick.db_obj + obj.db_liteattributes.add(lattr) for nick in orm['players.PlayerNick'].objects.all(): - try: - db.start_transaction() - lattr = orm.LiteAttribute(db_key=nick.db_nick, db_category="player_nick_%s" % nick.db_type, db_data=nick.db_real) - lattr.save() - obj = nick.db_obj - obj.db_liteattributes.add(lattr) - db.commit_transaction() - except IntegrityError: - db.commit_transaction() - print "Nick already exists: %s for %s" % (nick.db_nick, nick.db_obj.db_key) - # South expects the migration to be transaction managed. So start up a - # new transaction for it to close immediately when it exits this function. - db.start_transaction() - + lattr = orm.LiteAttribute(db_key=nick.db_nick, db_category="player_nick_%s" % nick.db_type, db_data=nick.db_real) + lattr.save() + obj = nick.db_obj + obj.db_liteattributes.add(lattr) def backwards(self, orm): "Write your backwards methods here." From 66802f291d5e3612dbeef9a63a539ee580f7b106 Mon Sep 17 00:00:00 2001 From: Kelketek Date: Mon, 22 Jul 2013 08:59:11 -0500 Subject: [PATCH 48/49] Updated news models to use custom user. No migration should be needed. Updated website templates. --- src/settings_default.py | 2 +- src/web/news/models.py | 4 +++- src/web/templates/prosimii/index.html | 2 +- src/web/templates/prosimii/registration/login.html | 3 ++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/settings_default.py b/src/settings_default.py index f54b2bc332..02e1235620 100644 --- a/src/settings_default.py +++ b/src/settings_default.py @@ -486,7 +486,7 @@ INSTALLED_APPS = ( 'src.comms', 'src.help', 'src.scripts', - #'src.web.news', + 'src.web.news', 'src.web.website',) # The user profile extends the User object with more functionality; # This should usually not be changed. diff --git a/src/web/news/models.py b/src/web/news/models.py index 9ea8f54953..d89d3362df 100755 --- a/src/web/news/models.py +++ b/src/web/news/models.py @@ -5,7 +5,9 @@ # from django.db import models -from django.contrib.auth.models import User +from django.contrib.auth import get_user_model + +User = get_user_model() class NewsTopic(models.Model): """ diff --git a/src/web/templates/prosimii/index.html b/src/web/templates/prosimii/index.html index c4b9d377bc..ff98d70eb0 100644 --- a/src/web/templates/prosimii/index.html +++ b/src/web/templates/prosimii/index.html @@ -58,7 +58,7 @@

Recently Connected

    {% for player in players_connected_recent %} -
  • {{player.user.username}} -- {{player.user.last_login|timesince}} ago
  • +
  • {{player.username}} -- {{player.last_login|timesince}} ago
  • {% endfor %}

diff --git a/src/web/templates/prosimii/registration/login.html b/src/web/templates/prosimii/registration/login.html index 94e312e1cd..4497a9aaa8 100644 --- a/src/web/templates/prosimii/registration/login.html +++ b/src/web/templates/prosimii/registration/login.html @@ -13,7 +13,8 @@ Login

Your username and password didn't match. Please try again.

{% endif %} -
+ + {% csrf_token %} From 5320381060df938ab84e06cc77e56944067d6f3b Mon Sep 17 00:00:00 2001 From: Kelketek Date: Sat, 27 Jul 2013 18:59:39 -0500 Subject: [PATCH 49/49] Removed some references to get_profile(), fixed some spelling errors, fixed post_clear signal. --- locale/sv/LC_MESSAGES/django.po | 2 +- src/commands/cmdparser.py | 2 +- src/commands/default/admin.py | 32 +++++++++++++---------------- src/commands/default/syscommands.py | 2 +- src/comms/managers.py | 1 - src/players/admin.py | 13 ++++++------ src/players/models.py | 15 ++++---------- src/server/caches.py | 12 +++++++---- src/server/initial_setup.py | 5 +---- 9 files changed, 37 insertions(+), 47 deletions(-) diff --git a/locale/sv/LC_MESSAGES/django.po b/locale/sv/LC_MESSAGES/django.po index c3eb93fd34..ab1016686f 100644 --- a/locale/sv/LC_MESSAGES/django.po +++ b/locale/sv/LC_MESSAGES/django.po @@ -37,7 +37,7 @@ msgid " Type \"help\" for help." msgstr "Skriv \"help\" för hjälp." #: src/commands/cmdhandler.py:212 -msgid "There where multiple matches." +msgid "There were multiple matches." msgstr "Det fanns många träffar." #: src/commands/cmdparser.py:144 diff --git a/src/commands/cmdparser.py b/src/commands/cmdparser.py index 386ed8f0c6..1b4650eaa2 100644 --- a/src/commands/cmdparser.py +++ b/src/commands/cmdparser.py @@ -245,7 +245,7 @@ def at_multimatch_cmd(caller, matches): """ Format multiple command matches to a useful error. """ - string = "There where multiple matches:" + string = "There were multiple matches:" for num, match in enumerate(matches): # each match is a tuple (candidate, cmd) cmdname, arg, cmd, dum, dum = match diff --git a/src/commands/default/admin.py b/src/commands/default/admin.py index 4eb8e6ec7e..861f875247 100644 --- a/src/commands/default/admin.py +++ b/src/commands/default/admin.py @@ -298,12 +298,8 @@ class CmdDelPlayer(MuxCommand): string = "No Player nor User found matching '%s'." % args self.msg(string) return - try: - player = user.get_profile() - except Exception: - player = None - if player and not player.access(caller, 'delete'): + if user and not user.access(caller, 'delete'): string = "You don't have the permissions to delete this player." self.msg(string) return @@ -311,9 +307,9 @@ class CmdDelPlayer(MuxCommand): string = "" name = user.username user.delete() - if player: - name = player.name - player.delete() + if user: + name = user.name + user.delete() string = "Player %s was deleted." % name else: string += "The User %s was deleted. It had no Player associated with it." % name @@ -322,16 +318,16 @@ class CmdDelPlayer(MuxCommand): elif utils.is_iter(players): string = "There were multiple matches:" - for player in players: - string += "\n %s %s" % (player.id, player.key) + for user in players: + string += "\n %s %s" % (user.id, user.key) return else: # one single match - player = players - user = player.user + user = players + user = user.user - if not player.access(caller, 'delete'): + if not user.access(caller, 'delete'): string = "You don't have the permissions to delete that player." self.msg(string) return @@ -342,12 +338,12 @@ class CmdDelPlayer(MuxCommand): string = "\nYour account '%s' is being *permanently* deleted.\n" % uname if reason: string += " Reason given:\n '%s'" % reason - player.unpuppet_all() - for session in SESSIONS.sessions_from_player(player): - player.msg(string, sessid=session.sessid) - player.disconnect_session_from_player(session.sessid) + user.unpuppet_all() + for session in SESSIONS.sessions_from_player(user): + user.msg(string, sessid=session.sessid) + user.disconnect_session_from_player(session.sessid) + user.delete() user.delete() - player.delete() self.msg("Player %s was successfully deleted." % uname) diff --git a/src/commands/default/syscommands.py b/src/commands/default/syscommands.py index ccd46f9e9d..cab02d66dd 100644 --- a/src/commands/default/syscommands.py +++ b/src/commands/default/syscommands.py @@ -88,7 +88,7 @@ class SystemMultimatch(MuxCommand): src.commands.cmdhandler. """ - string = "There where multiple matches:" + string = "There were multiple matches:" for num, match in enumerate(matches): # each match is a tuple (candidate, cmd) candidate, cmd = match diff --git a/src/comms/managers.py b/src/comms/managers.py index 118fcc5039..d54cba0391 100644 --- a/src/comms/managers.py +++ b/src/comms/managers.py @@ -65,7 +65,6 @@ def identify_object(inp): obj = inp typ = type(obj) if typ == _PlayerDB: return obj, "player" - if typ == _User: return obj.get_profile(), "player" elif typ == _ObjectDB: return obj, "object" elif typ == _Channel: return obj, "channel" elif dbref(obj): return dbref(obj), "dbref" diff --git a/src/players/admin.py b/src/players/admin.py index bac20f2a2f..52db397665 100644 --- a/src/players/admin.py +++ b/src/players/admin.py @@ -33,7 +33,7 @@ class PlayerDBChangeForm(UserChangeForm): username = self.cleaned_data['username'] if username.upper() == self.instance.username.upper(): return username - elif User.objects.filter(username__iexact=username): + elif PlayerDB.objects.filter(username__iexact=username): raise forms.ValidationError('A player with that name already exists.') return self.cleaned_data['username'] @@ -52,7 +52,7 @@ class PlayerDBCreationForm(UserCreationForm): def clean_username(self): username = self.cleaned_data['username'] - if User.objects.filter(username__iexact=username): + if PlayerDB.objects.filter(username__iexact=username): raise forms.ValidationError('A player with that name already exists.') return username @@ -139,7 +139,9 @@ class PlayerDBAdmin(BaseUserAdmin): ('Website dates', {'fields': ('last_login', 'date_joined'), 'description':'Relevant only to the website.'}), ('Website Permissions', {'fields': ('is_active', 'is_staff', 'is_superuser', 'user_permissions','groups'), - 'description': "These are permissions/permission groups for accessing the admin site. They are unrelated to in-game access rights."}),) + 'description': "These are permissions/permission groups for accessing the admin site. They are unrelated to in-game access rights."}), + ('Game Options', {'fields': ('db_typeclass_path', 'db_cmdset_storage', 'db_permissions', 'db_lock_storage'), + 'description': 'These are attributes that are more relevant to gameplay.'})) add_fieldsets = ( @@ -152,8 +154,7 @@ class PlayerDBAdmin(BaseUserAdmin): "Run all hooks on the player object" super(PlayerDBAdmin, self).save_formset(request, form, formset, change) userobj = form.instance - playerobj = userobj.get_profile() - playerobj.name = userobj.username + userobj.name = userobj.username if not change: #uname, passwd, email = str(request.POST.get(u"username")), \ # str(request.POST.get(u"password1")), str(request.POST.get(u"email")) @@ -161,6 +162,6 @@ class PlayerDBAdmin(BaseUserAdmin): create.create_player("","","", user=userobj, typeclass=typeclass, - player_dbobj=playerobj) + player_dbobj=userobj) admin.site.register(PlayerDB, PlayerDBAdmin) diff --git a/src/players/models.py b/src/players/models.py index 9f2f1eadfb..1b28ee7885 100644 --- a/src/players/models.py +++ b/src/players/models.py @@ -1,21 +1,14 @@ """ Player -The Player class is a simple extension of the django User model using -the 'profile' system of django. A profile is a model that tack new -fields to the User model without actually editing the User model -(which would mean hacking into django internals which we want to avoid -for future compatability reasons). The profile, which we call -'Player', is accessed with user.get_profile() by the property 'player' -defined on ObjectDB objects. Since we can customize it, we will try to -abstract as many operations as possible to work on Player rather than -on User. +The player class is an extension of the default Django user class, +and is customized for the needs of Evennia. We use the Player to store a more mud-friendly style of permission system as well as to allow the admin more flexibility by storing attributes on the Player. Within the game we should normally use the -Player manager's methods to create users, since that automatically -adds the profile extension. +Player manager's methods to create users so that permissions are set +correctly. To make the Player model more flexible for your own game, it can also persistently store attributes of its own. This is ideal for extra diff --git a/src/server/caches.py b/src/server/caches.py index b4d2707001..54941a88c0 100644 --- a/src/server/caches.py +++ b/src/server/caches.py @@ -172,6 +172,8 @@ def post_attr_update(sender, **kwargs): pass else: # forward relation changed (the Object holding the Attribute m2m field) + if not kwargs["pk_set"]: + return if action == "post_add": # cache all added objects for attr_id in kwargs["pk_set"]: @@ -185,10 +187,7 @@ def post_attr_update(sender, **kwargs): attr_obj.delete() elif action == "post_clear": # obj.db_attributes.clear() was called - for attr_id in kwargs["pk_set"]: - attr_obj = model.objects.get(pk=attr_id) - del_attr_cache(obj, _GA(attr_obj, "db_key")) - attr_obj.delete() + clear_obj_attr_cache(obj) # access methods @@ -215,6 +214,11 @@ def flush_attr_cache(): global _ATTR_CACHE _ATTR_CACHE = {} +def clear_obj_attr_cache(obj): + global _ATTR_CACHE + hid = hashid(obj) + _ATTR_CACHE = {key:value for key, value in _ATTR_CACHE if not key.startswith(hid)} + #------------------------------------------------------------ # Property cache - this is a generic cache for properties stored on models. #------------------------------------------------------------ diff --git a/src/server/initial_setup.py b/src/server/initial_setup.py index c81a97965f..b49de392ca 100644 --- a/src/server/initial_setup.py +++ b/src/server/initial_setup.py @@ -51,10 +51,7 @@ def create_objects(): god_player = get_god_player() # Create a Player 'user profile' object to hold eventual - # mud-specific settings for the bog standard User object. This is - # accessed by user.get_profile() and can also store attributes. - # It also holds mud permissions, but for a superuser these - # have no effect anyhow. + # mud-specific settings for the PlayerDB object. player_typeclass = settings.BASE_PLAYER_TYPECLASS # run all creation hooks on god_player (we must do so manually since the manage.py command does not)