From 29f78ae601bd38e4f87d54ea0bd96518ed85f093 Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 30 Jan 2020 09:55:18 +0100 Subject: [PATCH 01/45] Don't cause exception on unknown telnet disable negotiation. Addresses #2044 (but does not yet fix it). --- evennia/server/portal/telnet.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/evennia/server/portal/telnet.py b/evennia/server/portal/telnet.py index 41bb64fe9c..657c59c662 100644 --- a/evennia/server/portal/telnet.py +++ b/evennia/server/portal/telnet.py @@ -225,7 +225,11 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session): self.mccp.no_mccp(option) return True else: - return super().disableLocal(option) + try: + return super().disableLocal(option) + except Exception: + from evennia.utils import logger + logger.log_trace() def connectionLost(self, reason): """ From 85db61195225c41ec5368a165bec88760dfa11cd Mon Sep 17 00:00:00 2001 From: Andrew Bastien Date: Mon, 27 Jan 2020 09:35:31 -0500 Subject: [PATCH 02/45] Fixing up ANSIString --- evennia/utils/ansi.py | 45 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/evennia/utils/ansi.py b/evennia/utils/ansi.py index ec2b1b3378..265ce774ae 100644 --- a/evennia/utils/ansi.py +++ b/evennia/utils/ansi.py @@ -673,6 +673,10 @@ class ANSIString(str, metaclass=ANSIMeta): and taken literally the second time around. """ + # A compiled Regex for the format mini-language: https://docs.python.org/3/library/string.html#formatspec + re_format = re.compile(r"(?i)(?P(?P.)?(?P\<|\>|\=|\^))?(?P\+|\-| )?(?P\#)?" + r"(?P0)?(?P\d+)?(?P\_|\,)?(?:\.(?P\d+))?" + r"(?Pb|c|d|e|E|f|F|g|G|n|o|s|x|X|%)?") def __new__(cls, *args, **kwargs): """ @@ -733,6 +737,47 @@ class ANSIString(str, metaclass=ANSIMeta): def __str__(self): return self._raw_string + def __format__(self, format_spec): + """ + This magic method covers ANSIString's behavior within a str.format() or f-string. + + Current features supported: fill, align, width. + + Args: + format_spec (str): The format specification passed by f-string or str.format(). This is a string such as + "0<30" which would mean "left justify to 30, filling with zeros". The full specification can be found + at https://docs.python.org/3/library/string.html#formatspec + + Returns: + ansi_str (str): The formatted ANSIString's .raw() form, for display. + """ + # This calls the compiled regex stored on ANSIString's class to analyze the format spec. + # It returns a dictionary. + format_data = self.re_format.match(format_spec).groupdict() + clean = self.clean() + base_output = ANSIString(self.raw()) + align = format_data.get('align', '<') + fill = format_data.get('fill', ' ') + + # Need to coerce width into an integer. We can be certain that it's numeric thanks to regex. + width = format_data.get('width', None) + if width is None: + width = len(clean) + else: + width = int(width) + + if align == '<': + base_output = self.ljust(width, fill) + elif align == '>': + base_output = self.rjust(width, fill) + elif align == '^': + base_output = self.center(width, fill) + elif align == '=': + pass + + # Return the raw string with ANSI markup, ready to be displayed. + return base_output.raw() + def __repr__(self): """ Let's make the repr the command that would actually be used to From 8c5fdbe27f08db9d1dbb7e6aaa853d5befd14f04 Mon Sep 17 00:00:00 2001 From: Andrew Bastien Date: Wed, 29 Jan 2020 18:17:22 -0500 Subject: [PATCH 03/45] Adding unit tests for ANSIString! --- evennia/utils/tests/test_utils.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/evennia/utils/tests/test_utils.py b/evennia/utils/tests/test_utils.py index c969a988a5..eb01e38a83 100644 --- a/evennia/utils/tests/test_utils.py +++ b/evennia/utils/tests/test_utils.py @@ -98,6 +98,30 @@ class TestMLen(TestCase): self.assertEqual(utils.m_len({"hello": True, "Goodbye": False}), 2) +class TestANSIString(TestCase): + """ + Verifies that ANSIString's string-API works as intended. + """ + + def setUp(self): + self.example_raw = "|relectric |cboogaloo|n" + self.example_ansi = ANSIString(self.example_raw) + self.example_str = "electric boogaloo" + self.example_output = "\x1b[1m\x1b[31melectric \x1b[1m\x1b[36mboogaloo\x1b[0m" + + def test_length(self): + self.assertEqual(len(self.example_ansi), 17) + + def test_clean(self): + self.assertEqual(self.example_ansi.clean(), self.example_str) + + def test_raw(self): + self.assertEqual(self.example_ansi.raw(), self.example_output) + + def test_format(self): + self.assertEqual(f"{self.example_ansi:0<20}", self.example_output + "000") + + class TestTimeformat(TestCase): """ Default function header from utils.py: From 03356465db6afe8f15b792f26a1f0c62d3bc5c51 Mon Sep 17 00:00:00 2001 From: Griatch Date: Sat, 1 Feb 2020 21:32:26 +0100 Subject: [PATCH 04/45] Fix MSDP byte conversion errors, as per #2044 --- evennia/server/inputfuncs.py | 13 +++++++-- evennia/server/portal/mccp.py | 3 +- evennia/server/portal/mssp.py | 13 +++++---- evennia/server/portal/mxp.py | 3 +- evennia/server/portal/naws.py | 5 ++-- evennia/server/portal/suppress_ga.py | 4 ++- evennia/server/portal/telnet.py | 14 ++++++++++ evennia/server/portal/telnet_oob.py | 42 +++++++++++++++------------- evennia/server/portal/ttype.py | 7 +++-- 9 files changed, 68 insertions(+), 36 deletions(-) diff --git a/evennia/server/inputfuncs.py b/evennia/server/inputfuncs.py index bdf82c07c2..04135a630b 100644 --- a/evennia/server/inputfuncs.py +++ b/evennia/server/inputfuncs.py @@ -576,8 +576,7 @@ def msdp_list(session, *args, **kwargs): fieldnames = [tup[1] for tup in monitor_infos] session.msg(reported_variables=(fieldnames, {})) if "sendable_variables" in args_lower: - # no default sendable variables - session.msg(sendable_variables=([], {})) + session.msg(sendable_variables=(_monitorable, {})) def msdp_report(session, *args, **kwargs): @@ -597,6 +596,16 @@ def msdp_unreport(session, *args, **kwargs): unmonitor(session, *args, **kwargs) +def msdp_send(session, *args, **kwargs): + """ + MSDP SEND command + """ + out = {} + for varname in args: + if varname.lower() in _monitorable: + out[varname] = _monitorable[varname.lower()] + session.msg(send=((), out)) + # client specific diff --git a/evennia/server/portal/mccp.py b/evennia/server/portal/mccp.py index 3ca35ff4de..2d00e479b6 100644 --- a/evennia/server/portal/mccp.py +++ b/evennia/server/portal/mccp.py @@ -15,9 +15,10 @@ This protocol is implemented by the telnet protocol importing mccp_compress and calling it from its write methods. """ import zlib +from twisted.python.compat import _bytesChr as chr # negotiations for v1 and v2 of the protocol -MCCP = b"\x56" +MCCP = chr(86) # b"\x56" FLUSH = zlib.Z_SYNC_FLUSH diff --git a/evennia/server/portal/mssp.py b/evennia/server/portal/mssp.py index 20331741ed..81095b0cd9 100644 --- a/evennia/server/portal/mssp.py +++ b/evennia/server/portal/mssp.py @@ -12,10 +12,11 @@ active players and so on. """ from django.conf import settings from evennia.utils import utils +from twisted.python.compat import _bytesChr as bchr -MSSP = b"\x46" -MSSP_VAR = b"\x01" -MSSP_VAL = b"\x02" +MSSP = bchr(70) # b"\x46" +MSSP_VAR = bchr(1) # b"\x01" +MSSP_VAL = bchr(2) # b"\x02" # try to get the customized mssp info, if it exists. MSSPTable_CUSTOM = utils.variable_from_module(settings.MSSP_META_MODULE, "MSSPTable", default={}) @@ -85,7 +86,7 @@ class Mssp(object): "NAME": settings.SERVERNAME, "PLAYERS": self.get_player_count, "UPTIME": self.get_uptime, - "PORT": list( + "PORT": list(str(port) for port in reversed(settings.TELNET_PORTS) ), # most important port should be last in list # Evennia auto-filled @@ -119,10 +120,10 @@ class Mssp(object): if utils.is_iter(value): for partval in value: varlist += ( - MSSP_VAR + bytes(variable, "utf-8") + MSSP_VAL + bytes(partval, "utf-8") + MSSP_VAR + bytes(str(variable), "utf-8") + MSSP_VAL + bytes(str(partval), "utf-8") ) else: - varlist += MSSP_VAR + bytes(variable, "utf-8") + MSSP_VAL + bytes(value, "utf-8") + varlist += MSSP_VAR + bytes(str(variable), "utf-8") + MSSP_VAL + bytes(str(value), "utf-8") # send to crawler by subnegotiation self.protocol.requestNegotiation(MSSP, varlist) diff --git a/evennia/server/portal/mxp.py b/evennia/server/portal/mxp.py index c1d9e7422c..8ff773036d 100644 --- a/evennia/server/portal/mxp.py +++ b/evennia/server/portal/mxp.py @@ -14,11 +14,12 @@ http://www.gammon.com.au/mushclient/addingservermxp.htm """ import re +from twisted.python.compat import _bytesChr as bchr LINKS_SUB = re.compile(r"\|lc(.*?)\|lt(.*?)\|le", re.DOTALL) # MXP Telnet option -MXP = b"\x5b" +MXP = bchr(91) # b"\x5b" MXP_TEMPSECURE = "\x1B[4z" MXP_SEND = MXP_TEMPSECURE + '' + "\\2" + MXP_TEMPSECURE + "" diff --git a/evennia/server/portal/naws.py b/evennia/server/portal/naws.py index 737ba74845..caa9f73402 100644 --- a/evennia/server/portal/naws.py +++ b/evennia/server/portal/naws.py @@ -11,9 +11,10 @@ client and update it when the size changes """ from codecs import encode as codecs_encode from django.conf import settings +from twisted.python.compat import _bytesChr as bchr -NAWS = b"\x1f" -IS = b"\x00" +NAWS = bchr(31) # b"\x1f" +IS = bchr(0) # b"\x00" # default taken from telnet specification DEFAULT_WIDTH = settings.CLIENT_DEFAULT_WIDTH DEFAULT_HEIGHT = settings.CLIENT_DEFAULT_HEIGHT diff --git a/evennia/server/portal/suppress_ga.py b/evennia/server/portal/suppress_ga.py index 2e8f38808a..a295582a26 100644 --- a/evennia/server/portal/suppress_ga.py +++ b/evennia/server/portal/suppress_ga.py @@ -13,7 +13,9 @@ It is set as the NOGOAHEAD protocol_flag option. http://www.faqs.org/rfcs/rfc858.html """ -SUPPRESS_GA = b"\x03" +from twisted.python.compat import _bytesChr as bchr + +SUPPRESS_GA = bchr(3) # b"\x03" # default taken from telnet specification diff --git a/evennia/server/portal/telnet.py b/evennia/server/portal/telnet.py index 657c59c662..02a4808a2d 100644 --- a/evennia/server/portal/telnet.py +++ b/evennia/server/portal/telnet.py @@ -75,6 +75,20 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session): self.protocol_key = "telnet" super().__init__(*args, **kwargs) + def dataReceived(self, data): + print(f"indata: {data}") + super().dataReceived(data) + + def wont_no_true(self, state, option): + from evennia.utils import logger + logger.log_err(f"wont_no_true {self}, {state}, {option}") + super().wont_no_true(state, options) + + def dont_no_true(self, state, option): + from evennia.utils import logger + logger.log_err(f"dont_no_true {self}, {state}, {option}") + super().dont_no_true(state, options) + def connectionMade(self): """ This is called when the connection is first established. diff --git a/evennia/server/portal/telnet_oob.py b/evennia/server/portal/telnet_oob.py index f6e156f5a4..d160ed9e56 100644 --- a/evennia/server/portal/telnet_oob.py +++ b/evennia/server/portal/telnet_oob.py @@ -28,22 +28,24 @@ header where applicable. import re import json from evennia.utils.utils import is_iter - -# MSDP-relevant telnet cmd/opt-codes -MSDP = b"\x45" -MSDP_VAR = b"\x01" # ^A -MSDP_VAL = b"\x02" # ^B -MSDP_TABLE_OPEN = b"\x03" # ^C -MSDP_TABLE_CLOSE = b"\x04" # ^D -MSDP_ARRAY_OPEN = b"\x05" # ^E -MSDP_ARRAY_CLOSE = b"\x06" # ^F - -# GMCP -GMCP = b"\xc9" - +from twisted.python.compat import _bytesChr as bchr # General Telnet from twisted.conch.telnet import IAC, SB, SE +# MSDP-relevant telnet cmd/opt-codes +MSDP = bchr(69) +MSDP_VAR = bchr(1) +MSDP_VAL = bchr(2) +MSDP_TABLE_OPEN = bchr(3) +MSDP_TABLE_CLOSE = bchr(4) + +MSDP_ARRAY_OPEN = bchr(5) +MSDP_ARRAY_CLOSE = bchr(6) + +# GMCP +GMCP = bchr(201) + + # pre-compiled regexes # returns 2-tuple @@ -168,7 +170,7 @@ class TelnetOOB(object): """ msdp_cmdname = "{msdp_var}{msdp_cmdname}{msdp_val}".format( - msdp_var=MSDP_VAR, msdp_cmdname=cmdname, msdp_val=MSDP_VAL + msdp_var=MSDP_VAR.decode(), msdp_cmdname=cmdname, msdp_val=MSDP_VAL.decode() ) if not (args or kwargs): @@ -186,9 +188,9 @@ class TelnetOOB(object): "{msdp_array_open}" "{msdp_args}" "{msdp_array_close}".format( - msdp_array_open=MSDP_ARRAY_OPEN, - msdp_array_close=MSDP_ARRAY_CLOSE, - msdp_args="".join("%s%s" % (MSDP_VAL, json.dumps(val)) for val in args), + msdp_array_open=MSDP_ARRAY_OPEN.decode(), + msdp_array_close=MSDP_ARRAY_CLOSE.decode(), + msdp_args="".join("%s%s" % (MSDP_VAL.decode(), val) for val in args), ) ) @@ -199,10 +201,10 @@ class TelnetOOB(object): "{msdp_table_open}" "{msdp_kwargs}" "{msdp_table_close}".format( - msdp_table_open=MSDP_TABLE_OPEN, - msdp_table_close=MSDP_TABLE_CLOSE, + msdp_table_open=MSDP_TABLE_OPEN.decode(), + msdp_table_close=MSDP_TABLE_CLOSE.decode(), msdp_kwargs="".join( - "%s%s%s%s" % (MSDP_VAR, key, MSDP_VAL, json.dumps(val)) + "%s%s%s%s" % (MSDP_VAR.decode(), key, MSDP_VAL.decode(), val) for key, val in kwargs.items() ), ) diff --git a/evennia/server/portal/ttype.py b/evennia/server/portal/ttype.py index fb946bf9a2..01e7ebf74a 100644 --- a/evennia/server/portal/ttype.py +++ b/evennia/server/portal/ttype.py @@ -10,11 +10,12 @@ etc. If the client does not support TTYPE, this will be ignored. All data will be stored on the protocol's protocol_flags dictionary, under the 'TTYPE' key. """ +from twisted.python.compat import _bytesChr as bchr # telnet option codes -TTYPE = b"\x18" -IS = b"\x00" -SEND = b"\x01" +TTYPE = bchr(24) # b"\x18" +IS = bchr(0) # b"\x00" +SEND = bchr(1) # b"\x01" # terminal capabilities and their codes MTTS = [ From 60f5b8c1007eed1fc53b6f24950c6b121186effe Mon Sep 17 00:00:00 2001 From: Griatch Date: Sat, 1 Feb 2020 23:00:29 +0100 Subject: [PATCH 05/45] Fix annoying OptionRefused error when connecting from many clients --- evennia/server/portal/telnet.py | 42 +++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/evennia/server/portal/telnet.py b/evennia/server/portal/telnet.py index 02a4808a2d..fa46c366f8 100644 --- a/evennia/server/portal/telnet.py +++ b/evennia/server/portal/telnet.py @@ -76,26 +76,20 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session): super().__init__(*args, **kwargs) def dataReceived(self, data): - print(f"indata: {data}") + """ + Unused by default, but a good place to put debug printouts + of incoming data. + """ + # print(f"telnet dataReceived: {data}") super().dataReceived(data) - def wont_no_true(self, state, option): - from evennia.utils import logger - logger.log_err(f"wont_no_true {self}, {state}, {option}") - super().wont_no_true(state, options) - - def dont_no_true(self, state, option): - from evennia.utils import logger - logger.log_err(f"dont_no_true {self}, {state}, {option}") - super().dont_no_true(state, options) - def connectionMade(self): """ This is called when the connection is first established. """ # important in order to work normally with standard telnet - self.do(LINEMODE) + self.do(LINEMODE).addErrback(self._wont_linemode) # initialize the session self.line_buffer = b"" client_address = self.transport.client @@ -140,6 +134,15 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session): self.nop_keep_alive = None self.toggle_nop_keepalive() + def _wont_linemode(self, *args): + """ + Client refuses do(linemode). This is common for MUD-specific + clients, but we must ask for the sake of raw telnet. We ignore + this error. + """ + print("client refuses line mode") + pass + def _send_nop_keepalive(self): """Send NOP keepalive unless flag is set""" if self.protocol_flags.get("NOPKEEPALIVE"): @@ -195,7 +198,8 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session): if option == LINEMODE: # make sure to activate line mode with local editing for all clients self.requestNegotiation( - LINEMODE, MODE + bytes(chr(ord(LINEMODE_EDIT) + ord(LINEMODE_TRAPSIG)), "ascii") + LINEMODE, MODE + bytes(chr(ord(LINEMODE_EDIT) + + ord(LINEMODE_TRAPSIG)), "ascii") ) return True else: @@ -207,6 +211,16 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session): or option == suppress_ga.SUPPRESS_GA ) + def disableRemote(self, option): + return ( + option == LINEMODE + or option == ttype.TTYPE + or option == naws.NAWS + or option == MCCP + or option == mssp.MSSP + or option == suppress_ga.SUPPRESS_GA + ) + def enableLocal(self, option): """ Call to allow the activation of options for this protocol @@ -233,6 +247,8 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session): option (char): The telnet option to disable locally. """ + if option == LINEMODE: + return True if option == ECHO: return True if option == MCCP: From 67967b8aeb72b90f099d98e3e0e697b5388b5cac Mon Sep 17 00:00:00 2001 From: Griatch Date: Sat, 1 Feb 2020 23:06:37 +0100 Subject: [PATCH 06/45] Removing debug output --- evennia/server/portal/telnet.py | 1 - 1 file changed, 1 deletion(-) diff --git a/evennia/server/portal/telnet.py b/evennia/server/portal/telnet.py index fa46c366f8..0a926ab6d9 100644 --- a/evennia/server/portal/telnet.py +++ b/evennia/server/portal/telnet.py @@ -140,7 +140,6 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session): clients, but we must ask for the sake of raw telnet. We ignore this error. """ - print("client refuses line mode") pass def _send_nop_keepalive(self): From a8d569979d5973b634d1da4c5b54c7ae4e43efe8 Mon Sep 17 00:00:00 2001 From: Griatch Date: Sat, 1 Feb 2020 23:07:02 +0100 Subject: [PATCH 07/45] Ran black --- evennia/server/inputfuncs.py | 1 + evennia/server/portal/mssp.py | 13 +++++++++---- evennia/server/portal/telnet.py | 4 ++-- evennia/server/portal/telnet_oob.py | 2 +- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/evennia/server/inputfuncs.py b/evennia/server/inputfuncs.py index 04135a630b..24f74af19f 100644 --- a/evennia/server/inputfuncs.py +++ b/evennia/server/inputfuncs.py @@ -606,6 +606,7 @@ def msdp_send(session, *args, **kwargs): out[varname] = _monitorable[varname.lower()] session.msg(send=((), out)) + # client specific diff --git a/evennia/server/portal/mssp.py b/evennia/server/portal/mssp.py index 81095b0cd9..d939bcc37b 100644 --- a/evennia/server/portal/mssp.py +++ b/evennia/server/portal/mssp.py @@ -86,8 +86,8 @@ class Mssp(object): "NAME": settings.SERVERNAME, "PLAYERS": self.get_player_count, "UPTIME": self.get_uptime, - "PORT": list(str(port) for port in - reversed(settings.TELNET_PORTS) + "PORT": list( + str(port) for port in reversed(settings.TELNET_PORTS) ), # most important port should be last in list # Evennia auto-filled "CRAWL DELAY": "-1", @@ -120,10 +120,15 @@ class Mssp(object): if utils.is_iter(value): for partval in value: varlist += ( - MSSP_VAR + bytes(str(variable), "utf-8") + MSSP_VAL + bytes(str(partval), "utf-8") + MSSP_VAR + + bytes(str(variable), "utf-8") + + MSSP_VAL + + bytes(str(partval), "utf-8") ) else: - varlist += MSSP_VAR + bytes(str(variable), "utf-8") + MSSP_VAL + bytes(str(value), "utf-8") + varlist += ( + MSSP_VAR + bytes(str(variable), "utf-8") + MSSP_VAL + bytes(str(value), "utf-8") + ) # send to crawler by subnegotiation self.protocol.requestNegotiation(MSSP, varlist) diff --git a/evennia/server/portal/telnet.py b/evennia/server/portal/telnet.py index 0a926ab6d9..4dbee60f7d 100644 --- a/evennia/server/portal/telnet.py +++ b/evennia/server/portal/telnet.py @@ -197,8 +197,7 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session): if option == LINEMODE: # make sure to activate line mode with local editing for all clients self.requestNegotiation( - LINEMODE, MODE + bytes(chr(ord(LINEMODE_EDIT) + - ord(LINEMODE_TRAPSIG)), "ascii") + LINEMODE, MODE + bytes(chr(ord(LINEMODE_EDIT) + ord(LINEMODE_TRAPSIG)), "ascii") ) return True else: @@ -258,6 +257,7 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session): return super().disableLocal(option) except Exception: from evennia.utils import logger + logger.log_trace() def connectionLost(self, reason): diff --git a/evennia/server/portal/telnet_oob.py b/evennia/server/portal/telnet_oob.py index d160ed9e56..7931dcb2a4 100644 --- a/evennia/server/portal/telnet_oob.py +++ b/evennia/server/portal/telnet_oob.py @@ -29,6 +29,7 @@ import re import json from evennia.utils.utils import is_iter from twisted.python.compat import _bytesChr as bchr + # General Telnet from twisted.conch.telnet import IAC, SB, SE @@ -46,7 +47,6 @@ MSDP_ARRAY_CLOSE = bchr(6) GMCP = bchr(201) - # pre-compiled regexes # returns 2-tuple msdp_regex_table = re.compile( From a8de32da7f844964c70954853d22d3cc18a903a1 Mon Sep 17 00:00:00 2001 From: Griatch Date: Mon, 3 Feb 2020 08:51:09 +0100 Subject: [PATCH 08/45] Fix gendersub. Resolve #2038 --- evennia/contrib/gendersub.py | 40 +++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/evennia/contrib/gendersub.py b/evennia/contrib/gendersub.py index 09d8a2a006..627a4e3268 100644 --- a/evennia/contrib/gendersub.py +++ b/evennia/contrib/gendersub.py @@ -8,26 +8,39 @@ insert custom markers in their text to indicate gender-aware messaging. It relies on a modified msg() and is meant as an inspiration and starting point to how to do stuff like this. -When in use, all messages being sent to the character will make use of -the character's gender, for example the echo +An object can have the following genders: + - male (he/his) + - female (her/hers) + - neutral (it/its) + - ambiguous (they/them/their/theirs) + +When in use, messages can contain special tags to indicate pronouns gendered +based on the one being addressed. Capitalization will be retained. + +- `|s`, `|S`: Subjective form: he, she, it, He, She, It, They +- `|o`, `|O`: Objective form: him, her, it, Him, Her, It, Them +- `|p`, `|P`: Possessive form: his, her, its, His, Her, Its, Their +- `|a`, `|A`: Absolute Possessive form: his, hers, its, His, Hers, Its, Theirs + +For example, ``` char.msg("%s falls on |p face with a thud." % char.key) +"Tom falls on his face with a thud" ``` -will result in "Tom falls on his|her|its|their face with a thud" -depending on the gender of the object being messaged. Default gender -is "ambiguous" (they). +The default gender is "ambiguous" (they/them/their/theirs). To use, have DefaultCharacter inherit from this, or change setting.DEFAULT_CHARACTER to point to this class. -The `@gender` command needs to be added to the default cmdset before -it becomes available. +The `@gender` command is used to set the gender. It needs to be added to the +default cmdset before it becomes available. """ import re +from evennia.utils import logger from evennia import DefaultCharacter from evennia import Command @@ -114,7 +127,10 @@ class GenderCharacter(DefaultCharacter): gender-aware markers in output. Args: - text (str, optional): The message to send + text (str or tuple, optional): The message to send. This + is treated internally like any send-command, so its + value can be a tuple if sending multiple arguments to + the `text` oob command. from_obj (obj, optional): object that is sending. If given, at_msg_send will be called session (Session or list, optional): session or list of @@ -125,9 +141,13 @@ class GenderCharacter(DefaultCharacter): All extra kwargs will be passed on to the protocol. """ - # pre-process the text before continuing try: - text = _RE_GENDER_PRONOUN.sub(self._get_pronoun, text) + if text and isinstance(text, tuple): + text = (self._RE_GENDER_PRONOUN.sub(self._get_pronoun, text[0]), *text[1:]) + else: + text = self._RE_GENDER_PRONOUN.sub(self._get_pronoun, text) except TypeError: pass + except Exception as e: + logger.log_trace(e) super().msg(text, from_obj=from_obj, session=session, **kwargs) From 53cc7cd566eab5734ae1993afefbc4b59de2311b Mon Sep 17 00:00:00 2001 From: Griatch Date: Mon, 3 Feb 2020 21:15:19 +0100 Subject: [PATCH 09/45] Run black on sources --- evennia/utils/ansi.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/evennia/utils/ansi.py b/evennia/utils/ansi.py index 265ce774ae..21d1abd180 100644 --- a/evennia/utils/ansi.py +++ b/evennia/utils/ansi.py @@ -673,10 +673,13 @@ class ANSIString(str, metaclass=ANSIMeta): and taken literally the second time around. """ + # A compiled Regex for the format mini-language: https://docs.python.org/3/library/string.html#formatspec - re_format = re.compile(r"(?i)(?P(?P.)?(?P\<|\>|\=|\^))?(?P\+|\-| )?(?P\#)?" - r"(?P0)?(?P\d+)?(?P\_|\,)?(?:\.(?P\d+))?" - r"(?Pb|c|d|e|E|f|F|g|G|n|o|s|x|X|%)?") + re_format = re.compile( + r"(?i)(?P(?P.)?(?P\<|\>|\=|\^))?(?P\+|\-| )?(?P\#)?" + r"(?P0)?(?P\d+)?(?P\_|\,)?(?:\.(?P\d+))?" + r"(?Pb|c|d|e|E|f|F|g|G|n|o|s|x|X|%)?" + ) def __new__(cls, *args, **kwargs): """ @@ -756,23 +759,23 @@ class ANSIString(str, metaclass=ANSIMeta): format_data = self.re_format.match(format_spec).groupdict() clean = self.clean() base_output = ANSIString(self.raw()) - align = format_data.get('align', '<') - fill = format_data.get('fill', ' ') + align = format_data.get("align", "<") + fill = format_data.get("fill", " ") # Need to coerce width into an integer. We can be certain that it's numeric thanks to regex. - width = format_data.get('width', None) + width = format_data.get("width", None) if width is None: width = len(clean) else: width = int(width) - if align == '<': + if align == "<": base_output = self.ljust(width, fill) - elif align == '>': + elif align == ">": base_output = self.rjust(width, fill) - elif align == '^': + elif align == "^": base_output = self.center(width, fill) - elif align == '=': + elif align == "=": pass # Return the raw string with ANSI markup, ready to be displayed. From 5d594f25beb86c81b275001484fc5a9faff885cb Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 6 Feb 2020 16:35:58 +0100 Subject: [PATCH 10/45] Cleared out-of-date INSTALL.md file, pointing to online docs --- INSTALL.md | 136 +---------------------------------------------------- 1 file changed, 2 insertions(+), 134 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 8c45cb357e..926785ee5f 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,137 +1,5 @@ # Evennia installation -The latest and more detailed installation instructions can be found -[here](https://github.com/evennia/evennia/wiki/Getting-Started). - -## Installing Python - -First install [Python](https://www.python.org/). Linux users should -have it in their repositories, Windows/Mac users can get it from the -Python homepage. You need the 2.7.x version (Python 3 is not yet -supported). Windows users, make sure to select the option to make -Python available in your path - this is so you can call it everywhere -as `python`. Python 2.7.9 and later also includes the -[pip](https://pypi.python.org/pypi/pip/) installer out of the box, -otherwise install this separately (in linux it's usually found as the -`python-pip` package). - -### installing virtualenv - -This step is optional, but *highly* recommended. For installing -up-to-date Python packages we recommend using -[virtualenv](https://pypi.python.org/pypi/virtualenv), this makes it -easy to keep your Python packages up-to-date without interfering with -the defaults for your system. - -``` -pip install virtualenv -``` - -Go to the place where you want to make your virtual python library -storage. This does not need to be near where you plan to install -Evennia. Then do - -``` -virtualenv vienv -``` - -A new folder `vienv` will be created (you could also name it something -else if you prefer). Activate the virtual environment like this: - -``` -# for Linux/Unix/Mac: -source vienv/bin/activate -# for Windows: -vienv\Scripts\activate.bat -``` - -You should see `(vienv)` next to your prompt to show you the -environment is active. You need to activate it whenever you open a new -terminal, but you *don't* have to be inside the `vienv` folder henceforth. - - -## Get the developer's version of Evennia - -This is currently the only Evennia version available. First download -and install [Git](http://git-scm.com/) from the homepage or via the -package manager in Linux. Next, go to the place where you want the -`evennia` folder to be created and run - -``` -git clone https://github.com/evennia/evennia.git -``` - -If you have a github account and have [set up SSH -keys](https://help.github.com/articles/generating-ssh-keys/), you want -to use this instead: - -``` -git clone git@github.com:evennia/evennia.git -``` - -In the future you just enter the new `evennia` folder and do - -``` -git pull -``` - -to get the latest Evennia updates. - -## Evennia package install - -Stand at the root of your new `evennia` directory and run - -``` -pip install -e . -``` - -(note the period "." at the end, this tells pip to install from the -current directory). This will install Evennia and all its dependencies -(into your virtualenv if you are using that) and make the `evennia` -command available on the command line. You can find Evennia's -dependencies in `evennia/requirements.txt`. - -## Creating your game project - -To create your new game you need to initialize a new game project. -This should be done somewhere *outside* of your `evennia` folder. - - -``` -evennia --init mygame -``` - -This will create a new game project named "mygame" in a folder of the -same name. If you want to change the settings for your project, you -will need to edit `mygame/server/conf/settings.py`. - - -## Starting Evennia - -Enter your new game directory and run - -``` -evennia migrate -evennia start -``` - -Follow the instructions to create your superuser account. A lot of -information will scroll past as the database is created and the server -initializes. After this Evennia will be running. Use - -``` -evennia -h -``` - -for help with starting, stopping and other operations. - -Start up your MUD client of choice and point it to your server and -port *4000*. If you are just running locally the server name is -*localhost*. - -Alternatively, you can find the web interface and webclient by -pointing your web browser to *http://localhost:4001*. - -Finally, login with the superuser account and password you provided -earlier. Welcome to Evennia! +You can find the latest updated installation instructions and +requirements [here](https://github.com/evennia/evennia/wiki/Getting-Started). From 7a1918c327d8f9d3d7efbe9bee7e5d63f13a915a Mon Sep 17 00:00:00 2001 From: Ben Longden Date: Thu, 6 Feb 2020 20:27:27 +0000 Subject: [PATCH 11/45] Adds .decode() to byte stream to convert to string --- evennia/server/portal/telnet_ssl.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/evennia/server/portal/telnet_ssl.py b/evennia/server/portal/telnet_ssl.py index 1698d4faac..66fa606def 100644 --- a/evennia/server/portal/telnet_ssl.py +++ b/evennia/server/portal/telnet_ssl.py @@ -100,11 +100,11 @@ def verify_or_create_SSL_key_and_cert(keyfile, certfile): keypair.generate_key(crypto.TYPE_RSA, _PRIVATE_KEY_LENGTH) with open(_PRIVATE_KEY_FILE, "wt") as pfile: - pfile.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, keypair)) + pfile.write(crypto.dump_privatekey(crypto.FILETYPE_PEM, keypair).decode("utf-8")) print("Created SSL private key in '{}'.".format(_PRIVATE_KEY_FILE)) with open(_PUBLIC_KEY_FILE, "wt") as pfile: - pfile.write(crypto.dump_publickey(crypto.FILETYPE_PEM, keypair)) + pfile.write(crypto.dump_publickey(crypto.FILETYPE_PEM, keypair).decode("utf-8")) print("Created SSL public key in '{}'.".format(_PUBLIC_KEY_FILE)) except Exception as err: @@ -128,7 +128,7 @@ def verify_or_create_SSL_key_and_cert(keyfile, certfile): cert.sign(keypair, "sha1") with open(_CERTIFICATE_FILE, "wt") as cfile: - cfile.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)) + cfile.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode("utf-8")) print("Created SSL certificate in '{}'.".format(_CERTIFICATE_FILE)) except Exception as err: From ad8b1d81d59b9d80fe36c67dfccf47eeec24fffa Mon Sep 17 00:00:00 2001 From: trhr Date: Sun, 9 Feb 2020 19:52:10 -0600 Subject: [PATCH 12/45] django.utils.safestring.SafeBytes - Unused since Django 2.0. --- evennia/utils/dbserialize.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/evennia/utils/dbserialize.py b/evennia/utils/dbserialize.py index b3e55d1ca6..27fc43e1a1 100644 --- a/evennia/utils/dbserialize.py +++ b/evennia/utils/dbserialize.py @@ -28,11 +28,12 @@ except ImportError: from pickle import dumps, loads from django.core.exceptions import ObjectDoesNotExist from django.contrib.contenttypes.models import ContentType -from django.utils.safestring import SafeString, SafeBytes +from django.utils.safestring import SafeString from evennia.utils.utils import uses_database, is_iter, to_str, to_bytes from evennia.utils import logger -__all__ = ("to_pickle", "from_pickle", "do_pickle", "do_unpickle", "dbserialize", "dbunserialize") +__all__ = ("to_pickle", "from_pickle", "do_pickle", + "do_unpickle", "dbserialize", "dbunserialize") PICKLE_PROTOCOL = 2 @@ -116,13 +117,15 @@ def _init_globals(): global _FROM_MODEL_MAP, _TO_MODEL_MAP, _SESSION_HANDLER, _IGNORE_DATETIME_MODELS if not _FROM_MODEL_MAP: _FROM_MODEL_MAP = defaultdict(str) - _FROM_MODEL_MAP.update(dict((c.model, c.natural_key()) for c in ContentType.objects.all())) + _FROM_MODEL_MAP.update(dict((c.model, c.natural_key()) + for c in ContentType.objects.all())) if not _TO_MODEL_MAP: from django.conf import settings _TO_MODEL_MAP = defaultdict(str) _TO_MODEL_MAP.update( - dict((c.natural_key(), c.model_class()) for c in ContentType.objects.all()) + dict((c.natural_key(), c.model_class()) + for c in ContentType.objects.all()) ) _IGNORE_DATETIME_MODELS = [] for src_key, dst_key in settings.ATTRIBUTE_STORED_MODEL_RENAME: @@ -185,7 +188,8 @@ class _SaverMutable(object): ) self._db_obj.value = self else: - logger.log_err("_SaverMutable %s has no root Attribute to save to." % self) + logger.log_err( + "_SaverMutable %s has no root Attribute to save to." % self) def _convert_mutables(self, data): """converts mutables to Saver* variants and assigns ._parent property""" @@ -201,7 +205,8 @@ class _SaverMutable(object): return dat elif dtype == dict: dat = _SaverDict(_parent=parent) - dat._data.update((key, process_tree(val, dat)) for key, val in item.items()) + dat._data.update((key, process_tree(val, dat)) + for key, val in item.items()) return dat elif dtype == set: dat = _SaverSet(_parent=parent) @@ -549,7 +554,7 @@ def to_pickle(data): def process_item(item): """Recursive processor and identification of data""" dtype = type(item) - if dtype in (str, int, float, bool, bytes, SafeString, SafeBytes): + if dtype in (str, int, float, bool, bytes, SafeString): return item elif dtype == tuple: return tuple(process_item(val) for val in item) @@ -577,7 +582,8 @@ def to_pickle(data): except TypeError: return item except Exception: - logger.log_error(f"The object {item} of type {type(item)} could not be stored.") + logger.log_error( + f"The object {item} of type {type(item)} could not be stored.") raise return process_item(data) @@ -609,7 +615,7 @@ def from_pickle(data, db_obj=None): def process_item(item): """Recursive processor and identification of data""" dtype = type(item) - if dtype in (str, int, float, bool, bytes, SafeString, SafeBytes): + if dtype in (str, int, float, bool, bytes, SafeString): return item elif _IS_PACKED_DBOBJ(item): # this must be checked before tuple @@ -638,7 +644,7 @@ def from_pickle(data, db_obj=None): def process_tree(item, parent): """Recursive processor, building a parent-tree from iterable data""" dtype = type(item) - if dtype in (str, int, float, bool, bytes, SafeString, SafeBytes): + if dtype in (str, int, float, bool, bytes, SafeString): return item elif _IS_PACKED_DBOBJ(item): # this must be checked before tuple From ce95961663e9745ac26183259e7ab346516da6e7 Mon Sep 17 00:00:00 2001 From: trhr Date: Sun, 9 Feb 2020 19:54:20 -0600 Subject: [PATCH 13/45] The smart_text() and force_text() aliases (since Django 2.0) of smart_str() and force_str() are deprecated --- evennia/utils/picklefield.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/evennia/utils/picklefield.py b/evennia/utils/picklefield.py index c2b5abb98a..50408c5949 100644 --- a/evennia/utils/picklefield.py +++ b/evennia/utils/picklefield.py @@ -43,7 +43,7 @@ from django.forms.fields import CharField from django.forms.widgets import Textarea from pickle import loads, dumps -from django.utils.encoding import force_text +from django.utils.encoding import force_str DEFAULT_PROTOCOL = 4 @@ -210,10 +210,10 @@ class PickledObjectField(models.Field): """ Returns the default value for this field. - The default implementation on models.Field calls force_text + The default implementation on models.Field calls force_str on the default, which means you can't set arbitrary Python objects as the default. To fix this, we just return the value - without calling force_text on it. Note that if you set a + without calling force_str on it. Note that if you set a callable as a default, the field will still call it. It will *not* try to pickle and encode it. @@ -267,13 +267,13 @@ class PickledObjectField(models.Field): """ if value is not None and not isinstance(value, PickledObject): - # We call force_text here explicitly, so that the encoded string + # We call force_str here explicitly, so that the encoded string # isn't rejected by the postgresql_psycopg2 backend. Alternatively, # we could have just registered PickledObject with the psycopg # marshaller (telling it to store it like it would a string), but # since both of these methods result in the same value being stored, # doing things this way is much easier. - value = force_text(dbsafe_encode(value, self.compress, self.protocol)) + value = force_str(dbsafe_encode(value, self.compress, self.protocol)) return value def value_to_string(self, obj): From 090157979b79a577982d2b0a0b32084a4b774abc Mon Sep 17 00:00:00 2001 From: trhr Date: Sun, 9 Feb 2020 19:55:49 -0600 Subject: [PATCH 14/45] =?UTF-8?q?django.utils.translation.ugettext(),=20ug?= =?UTF-8?q?ettext=5Flazy(),=20ugettext=5Fnoop(),=20ungettext(),=20and=20un?= =?UTF-8?q?gettext=5Flazy()=20are=20deprecated=20in=20favor=20of=20the=20f?= =?UTF-8?q?unctions=20that=20they=E2=80=99re=20aliases=20for:=20django.uti?= =?UTF-8?q?ls.translation.gettext(),=20gettext=5Flazy(),=20gettext=5Fnoop(?= =?UTF-8?q?),=20ngettext(),=20and=20ngettext=5Flazy().?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- evennia/accounts/accounts.py | 2 +- evennia/commands/cmdhandler.py | 2 +- evennia/commands/cmdset.py | 2 +- evennia/commands/cmdsethandler.py | 2 +- evennia/comms/channelhandler.py | 2 +- evennia/locks/lockhandler.py | 2 +- evennia/objects/objects.py | 2 +- evennia/scripts/scripthandler.py | 2 +- evennia/scripts/scripts.py | 2 +- evennia/server/initial_setup.py | 2 +- evennia/server/server.py | 2 +- evennia/server/serversession.py | 2 +- evennia/server/sessionhandler.py | 2 +- evennia/utils/evmenu.py | 2 +- evennia/utils/utils.py | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/evennia/accounts/accounts.py b/evennia/accounts/accounts.py index f1bc45acf6..f3217e88ea 100644 --- a/evennia/accounts/accounts.py +++ b/evennia/accounts/accounts.py @@ -37,7 +37,7 @@ from evennia.scripts.scripthandler import ScriptHandler from evennia.commands.cmdsethandler import CmdSetHandler from evennia.utils.optionhandler import OptionHandler -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from random import getrandbits __all__ = ("DefaultAccount",) diff --git a/evennia/commands/cmdhandler.py b/evennia/commands/cmdhandler.py index 8ccbcbae93..6f8f247a72 100644 --- a/evennia/commands/cmdhandler.py +++ b/evennia/commands/cmdhandler.py @@ -48,7 +48,7 @@ from evennia.comms.channelhandler import CHANNELHANDLER from evennia.utils import logger, utils from evennia.utils.utils import string_suggestions -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ _IN_GAME_ERRORS = settings.IN_GAME_ERRORS diff --git a/evennia/commands/cmdset.py b/evennia/commands/cmdset.py index 5bb3ec8d28..f124bbbb06 100644 --- a/evennia/commands/cmdset.py +++ b/evennia/commands/cmdset.py @@ -27,7 +27,7 @@ Set theory. """ from weakref import WeakKeyDictionary -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from evennia.utils.utils import inherits_from, is_iter __all__ = ("CmdSet",) diff --git a/evennia/commands/cmdsethandler.py b/evennia/commands/cmdsethandler.py index e855d551e9..395c9c2ba3 100644 --- a/evennia/commands/cmdsethandler.py +++ b/evennia/commands/cmdsethandler.py @@ -72,7 +72,7 @@ from evennia.utils import logger, utils from evennia.commands.cmdset import CmdSet from evennia.server.models import ServerConfig -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ __all__ = ("import_cmdset", "CmdSetHandler") diff --git a/evennia/comms/channelhandler.py b/evennia/comms/channelhandler.py index feea9f6e33..98e28786a0 100644 --- a/evennia/comms/channelhandler.py +++ b/evennia/comms/channelhandler.py @@ -27,7 +27,7 @@ from django.conf import settings from evennia.commands import cmdset, command from evennia.utils.logger import tail_log_file from evennia.utils.utils import class_from_module -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ # we must late-import these since any overloads are likely to # themselves be using these classes leading to a circular import. diff --git a/evennia/locks/lockhandler.py b/evennia/locks/lockhandler.py index 22f5844e31..ac8c85abc8 100644 --- a/evennia/locks/lockhandler.py +++ b/evennia/locks/lockhandler.py @@ -107,7 +107,7 @@ to any other identifier you can use. import re from django.conf import settings from evennia.utils import logger, utils -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ __all__ = ("LockHandler", "LockException") diff --git a/evennia/objects/objects.py b/evennia/objects/objects.py index d980b88303..25731923e6 100644 --- a/evennia/objects/objects.py +++ b/evennia/objects/objects.py @@ -31,7 +31,7 @@ from evennia.utils.utils import ( list_to_string, to_str, ) -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ _INFLECT = inflect.engine() _MULTISESSION_MODE = settings.MULTISESSION_MODE diff --git a/evennia/scripts/scripthandler.py b/evennia/scripts/scripthandler.py index d2298a7ce2..d924636f8c 100644 --- a/evennia/scripts/scripthandler.py +++ b/evennia/scripts/scripthandler.py @@ -9,7 +9,7 @@ from evennia.scripts.models import ScriptDB from evennia.utils import create from evennia.utils import logger -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ class ScriptHandler(object): diff --git a/evennia/scripts/scripts.py b/evennia/scripts/scripts.py index 42bb1c8797..2f9bb5d5e2 100644 --- a/evennia/scripts/scripts.py +++ b/evennia/scripts/scripts.py @@ -8,7 +8,7 @@ ability to run timers. from twisted.internet.defer import Deferred, maybeDeferred from twisted.internet.task import LoopingCall from django.core.exceptions import ObjectDoesNotExist -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from evennia.typeclasses.models import TypeclassBase from evennia.scripts.models import ScriptDB from evennia.scripts.manager import ScriptManager diff --git a/evennia/server/initial_setup.py b/evennia/server/initial_setup.py index 8f7fd3300f..e0845c0859 100644 --- a/evennia/server/initial_setup.py +++ b/evennia/server/initial_setup.py @@ -9,7 +9,7 @@ Everything starts at handle_setup() import time from django.conf import settings -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from evennia.accounts.models import AccountDB from evennia.server.models import ServerConfig from evennia.utils import create, logger diff --git a/evennia/server/server.py b/evennia/server/server.py index 1c1783bef1..2093b5b88c 100644 --- a/evennia/server/server.py +++ b/evennia/server/server.py @@ -38,7 +38,7 @@ from evennia.utils import logger from evennia.comms import channelhandler from evennia.server.sessionhandler import SESSIONS -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ _SA = object.__setattr__ diff --git a/evennia/server/serversession.py b/evennia/server/serversession.py index 6ae0ec4b63..2443758b12 100644 --- a/evennia/server/serversession.py +++ b/evennia/server/serversession.py @@ -23,7 +23,7 @@ _ObjectDB = None _ANSI = None # i18n -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ # Handlers for Session.db/ndb operation diff --git a/evennia/server/sessionhandler.py b/evennia/server/sessionhandler.py index 1bf43746d6..0d099d6d30 100644 --- a/evennia/server/sessionhandler.py +++ b/evennia/server/sessionhandler.py @@ -67,7 +67,7 @@ PSTATUS = chr(18) # ping server or portal status SRESET = chr(19) # server shutdown in reset mode # i18n -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ _SERVERNAME = settings.SERVERNAME _MULTISESSION_MODE = settings.MULTISESSION_MODE diff --git a/evennia/utils/evmenu.py b/evennia/utils/evmenu.py index 0bc5b37475..ccf2840f91 100644 --- a/evennia/utils/evmenu.py +++ b/evennia/utils/evmenu.py @@ -187,7 +187,7 @@ _CMD_NOINPUT = cmdhandler.CMD_NOINPUT # Return messages # i18n -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ _ERR_NOT_IMPLEMENTED = _( "Menu node '{nodename}' is either not implemented or " "caused an error. Make another choice." diff --git a/evennia/utils/utils.py b/evennia/utils/utils.py index 49c8af1e7b..53fd73de42 100644 --- a/evennia/utils/utils.py +++ b/evennia/utils/utils.py @@ -27,7 +27,7 @@ from collections import defaultdict, OrderedDict from twisted.internet import threads, reactor from django.conf import settings from django.utils import timezone -from django.utils.translation import ugettext as _ +from django.utils.translation import gettext as _ from django.apps import apps from evennia.utils import logger From ce0a012e518781acd33259df9e20b7317fb8262c Mon Sep 17 00:00:00 2001 From: trhr Date: Sun, 9 Feb 2020 19:58:21 -0600 Subject: [PATCH 15/45] =?UTF-8?q?The=20django.db.backends.postgresql=5Fpsy?= =?UTF-8?q?copg2=20module=20is=20deprecated=20in=20favor=20of=20django.db.?= =?UTF-8?q?backends.postgresql.=20It=E2=80=99s=20been=20an=20alias=20since?= =?UTF-8?q?=20Django=201.9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .travis/postgresql_settings.py | 2 +- evennia/settings_default.py | 2 +- evennia/typeclasses/migrations/0010_delete_old_player_tables.py | 2 +- evennia/utils/picklefield.py | 2 +- evennia/utils/utils.py | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis/postgresql_settings.py b/.travis/postgresql_settings.py index 292cb9cc70..c12927af3a 100644 --- a/.travis/postgresql_settings.py +++ b/.travis/postgresql_settings.py @@ -40,7 +40,7 @@ SERVERNAME = "testing_mygame" DATABASES = { "default": { - "ENGINE": "django.db.backends.postgresql_psycopg2", + "ENGINE": "django.db.backends.postgresql", "NAME": "evennia", "USER": "evennia", "PASSWORD": "password", diff --git a/evennia/settings_default.py b/evennia/settings_default.py index b2a06e328e..5ecafb75b5 100644 --- a/evennia/settings_default.py +++ b/evennia/settings_default.py @@ -245,7 +245,7 @@ IN_GAME_ERRORS = True # ENGINE - path to the the database backend. Possible choices are: # 'django.db.backends.sqlite3', (default) # 'django.db.backends.mysql', -# 'django.db.backends.postgresql_psycopg2', +# 'django.db.backends.postgresql', # 'django.db.backends.oracle' (untested). # NAME - database name, or path to the db file for sqlite3 # USER - db admin (unused in sqlite3) diff --git a/evennia/typeclasses/migrations/0010_delete_old_player_tables.py b/evennia/typeclasses/migrations/0010_delete_old_player_tables.py index 0732f0fe99..32e1f80923 100644 --- a/evennia/typeclasses/migrations/0010_delete_old_player_tables.py +++ b/evennia/typeclasses/migrations/0010_delete_old_player_tables.py @@ -27,7 +27,7 @@ def _drop_table(db_cursor, table_name): db_cursor.execute("SET FOREIGN_KEY_CHECKS=0;") db_cursor.execute("DROP TABLE {table};".format(table=table_name)) db_cursor.execute("SET FOREIGN_KEY_CHECKS=1;") - elif _ENGINE == "postgresql_psycopg2": + elif _ENGINE == "postgresql": db_cursor.execute("ALTER TABLE {table} DISABLE TRIGGER ALL;".format(table=table_name)) db_cursor.execute("DROP TABLE {table};".format(table=table_name)) db_cursor.execute("ALTER TABLE {table} ENABLE TRIGGER ALL;".format(table=table_name)) diff --git a/evennia/utils/picklefield.py b/evennia/utils/picklefield.py index 50408c5949..084fc6d638 100644 --- a/evennia/utils/picklefield.py +++ b/evennia/utils/picklefield.py @@ -268,7 +268,7 @@ class PickledObjectField(models.Field): """ if value is not None and not isinstance(value, PickledObject): # We call force_str here explicitly, so that the encoded string - # isn't rejected by the postgresql_psycopg2 backend. Alternatively, + # isn't rejected by the postgresql backend. Alternatively, # we could have just registered PickledObject with the psycopg # marshaller (telling it to store it like it would a string), but # since both of these methods result in the same value being stored, diff --git a/evennia/utils/utils.py b/evennia/utils/utils.py index 53fd73de42..cc191fdd53 100644 --- a/evennia/utils/utils.py +++ b/evennia/utils/utils.py @@ -1036,7 +1036,7 @@ def uses_database(name="sqlite3"): shortcut to having to use the full backend name. Args: - name (str): One of 'sqlite3', 'mysql', 'postgresql_psycopg2' + name (str): One of 'sqlite3', 'mysql', 'postgresql' or 'oracle'. Returns: From 308818bd5d2d6270cba229e606e501ac41bf4e6a Mon Sep 17 00:00:00 2001 From: trhr Date: Sun, 9 Feb 2020 20:00:33 -0600 Subject: [PATCH 16/45] {% load staticfiles %} and {% load admin_static %} are deprecated in favor of {% load static %}, which works the same. --- evennia/web/webclient/templates/webclient/base.html | 2 +- evennia/web/website/templates/website/_menu.html | 2 +- evennia/web/website/templates/website/base.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/evennia/web/webclient/templates/webclient/base.html b/evennia/web/webclient/templates/webclient/base.html index 46353b18ad..e65467da12 100644 --- a/evennia/web/webclient/templates/webclient/base.html +++ b/evennia/web/webclient/templates/webclient/base.html @@ -6,7 +6,7 @@ with evennia set up automatically and get the Evennia JS lib and JQuery available. --> -{% load staticfiles %} +{% load static %} {{game_name}} diff --git a/evennia/web/website/templates/website/_menu.html b/evennia/web/website/templates/website/_menu.html index a947445167..3d6501fb45 100644 --- a/evennia/web/website/templates/website/_menu.html +++ b/evennia/web/website/templates/website/_menu.html @@ -3,7 +3,7 @@ Allow to customize the menu that appears at the top of every Evennia webpage. Copy this file to your game dir's web/template_overrides/website folder and edit it to add/remove links to the menu. {% endcomment %} -{% load staticfiles %} +{% load static %}