From 78dce264a5ef814050b6d96f1d7322be15610f29 Mon Sep 17 00:00:00 2001 From: Griatch Date: Sun, 1 Nov 2020 12:13:51 +0100 Subject: [PATCH 01/17] Update line number in doc ref. Resolves #2242. --- docs/source/Python-basic-tutorial-part-two.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/Python-basic-tutorial-part-two.md b/docs/source/Python-basic-tutorial-part-two.md index b1e0820a0d..7eebbd04d3 100644 --- a/docs/source/Python-basic-tutorial-part-two.md +++ b/docs/source/Python-basic-tutorial-part-two.md @@ -310,7 +310,7 @@ class DefaultCharacter(DefaultObject): This means that `DefaultCharacter` is in *itself* a child of something called `DefaultObject`! Let's see what this parent class provides. It's in the same module as `DefaultCharacter`, you just need to [scroll up near the -top](https://github.com/evennia/evennia/blob/master/evennia/objects/objects.py#L182): +top](https://github.com/evennia/evennia/blob/master/evennia/objects/objects.py#L193): ```python class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)): From 17dfcd4ed5e6e5186dd3fcc722e5cae7fbf41246 Mon Sep 17 00:00:00 2001 From: Griatch Date: Sun, 1 Nov 2020 16:12:56 +0100 Subject: [PATCH 02/17] Better report of tracebacks across AMP bridge, sort of related to #2240 --- evennia/server/portal/amp.py | 51 +++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/evennia/server/portal/amp.py b/evennia/server/portal/amp.py index 505ea5e3e0..6065a4fdfa 100644 --- a/evennia/server/portal/amp.py +++ b/evennia/server/portal/amp.py @@ -46,6 +46,14 @@ NULNUL = b"\x00\x00" AMP_MAXLEN = amp.MAX_VALUE_LENGTH # max allowed data length in AMP protocol (cannot be changed) +# amp internal +ASK = b'_ask' +ANSWER = b'_answer' +ERROR = b'_error' +ERROR_CODE = b'_error_code' +ERROR_DESCRIPTION = b'_error_description' +UNKNOWN_ERROR_CODE = b'UNKNOWN' + # buffers _SENDBATCH = defaultdict(list) _MSGBUFFER = defaultdict(list) @@ -301,6 +309,47 @@ class AMPMultiConnectionProtocol(amp.AMP): # later twisted amp has its own __init__ super(AMPMultiConnectionProtocol, self).__init__(*args, **kwargs) + def _commandReceived(self, box): + """ + This overrides the default Twisted AMP error handling which is not + passing enough of the traceback through to the other side. Instead we + add a specific log of the problem on the erroring side. + + """ + def formatAnswer(answerBox): + answerBox[ANSWER] = box[ASK] + return answerBox + + def formatError(error): + if error.check(amp.RemoteAmpError): + code = error.value.errorCode + desc = error.value.description + + # Evennia extra logging + desc += " (error logged on other side)" + _get_logger().log_err(f"AMP caught exception ({desc}):\n{error.value}") + + if isinstance(desc, str): + desc = desc.encode("utf-8", "replace") + if error.value.fatal: + errorBox = amp.QuitBox() + else: + errorBox = amp.AmpBox() + else: + errorBox = amp.QuitBox() + _get_logger().log_err(error) # server-side logging if unhandled error + code = UNKNOWN_ERROR_CODE + desc = b"Unknown Error" + errorBox[ERROR] = box[ASK] + errorBox[ERROR_DESCRIPTION] = desc + errorBox[ERROR_CODE] = code + return errorBox + deferred = self.dispatchCommand(box) + if ASK in box: + deferred.addCallbacks(formatAnswer, formatError) + deferred.addCallback(self._safeEmit) + deferred.addErrback(self.unhandledError) + def dataReceived(self, data): """ Handle non-AMP messages, such as HTTP communication. @@ -385,7 +434,7 @@ class AMPMultiConnectionProtocol(amp.AMP): """ e.trap(Exception) _get_logger().log_err( - "AMP Error for {info}: {trcbck} {err}".format( + "AMP Error from {info}: {trcbck} {err}".format( info=info, trcbck=e.getTraceback(), err=e.getErrorMessage() ) ) From a63be0a416b662f0e94830b648675796ae3f4220 Mon Sep 17 00:00:00 2001 From: Griatch Date: Sun, 1 Nov 2020 17:38:49 +0100 Subject: [PATCH 03/17] Make service/start/stop handle errors better. Resolve #2237. --- evennia/commands/default/system.py | 35 +++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/evennia/commands/default/system.py b/evennia/commands/default/system.py index 6ba160e489..d0a46b0f7d 100644 --- a/evennia/commands/default/system.py +++ b/evennia/commands/default/system.py @@ -840,21 +840,30 @@ class CmdService(COMMAND_DEFAULT_CLASS): return if service.name[:7] == "Evennia": if delmode: - caller.msg("You cannot remove a core Evennia service (named 'Evennia***').") + caller.msg("You cannot remove a core Evennia service (named 'Evennia*').") return - string = "You seem to be shutting down a core Evennia service (named 'Evennia***'). Note that" - string += "stopping some TCP port services will *not* disconnect users *already*" - string += "connected on those ports, but *may* instead cause spurious errors for them. To " - string += "safely and permanently remove ports, change settings file and restart the server." + string = ("|RYou seem to be shutting down a core Evennia " + "service (named 'Evennia*').\nNote that stopping " + "some TCP port services will *not* disconnect users " + "*already* connected on those ports, but *may* " + "instead cause spurious errors for them.\nTo safely " + "and permanently remove ports, change settings file " + "and restart the server.|n\n") caller.msg(string) if delmode: service.stopService() service_collection.removeService(service) - caller.msg("Stopped and removed service '%s'." % self.args) + caller.msg("|gStopped and removed service '%s'.|n" % self.args) else: - service.stopService() - caller.msg("Stopped service '%s'." % self.args) + caller.msg(f"Stopping service '{self.args}'...") + try: + service.stopService() + except Exception as err: + caller.msg(f"|rErrors were reported when stopping this service{err}.\n" + "If there are remaining problems, try reloading " + "or rebooting the server.") + caller.msg("|g... Stopped service '%s'.|n" % self.args) return if switches[0] == "start": @@ -862,8 +871,14 @@ class CmdService(COMMAND_DEFAULT_CLASS): if service.running: caller.msg("That service is already running.") return - caller.msg("Starting service '%s'." % self.args) - service.startService() + caller.msg(f"Starting service '{self.args}' ...") + try: + service.startService() + except Exception as err: + caller.msg(f"|rErrors were reported when starting this service{err}.\n" + "If there are remaining problems, try reloading the server, changing the " + "settings if it's a non-standard service.|n") + caller.msg("|gService started.|n") class CmdAbout(COMMAND_DEFAULT_CLASS): From 99aba2e4c9d8163e83cc89354afef20385538759 Mon Sep 17 00:00:00 2001 From: Griatch Date: Sun, 1 Nov 2020 19:02:46 +0100 Subject: [PATCH 04/17] Changing tab characters for webclient. Resolve #2239. --- evennia/utils/ansi.py | 4 ++-- evennia/utils/text2html.py | 2 +- evennia/web/webclient/static/webclient/css/webclient.css | 7 ++++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/evennia/utils/ansi.py b/evennia/utils/ansi.py index 370dda870d..e954590fbb 100644 --- a/evennia/utils/ansi.py +++ b/evennia/utils/ansi.py @@ -85,8 +85,7 @@ class ANSIParser(object): to ANSI command sequences We also allow to escape colour codes - by prepending with a \ for xterm256, - an extra | for Merc-style codes + by prepending with an extra |. """ @@ -97,6 +96,7 @@ class ANSIParser(object): (r"|n", ANSI_NORMAL), # reset (r"|/", ANSI_RETURN), # line break (r"|-", ANSI_TAB), # tab + (r"|>", ANSI_SPACE * 4), # indent (4 spaces) (r"|_", ANSI_SPACE), # space (r"|*", ANSI_INVERSE), # invert (r"|^", ANSI_BLINK), # blinking text (very annoying and not supported by all clients) diff --git a/evennia/utils/text2html.py b/evennia/utils/text2html.py index 847466aff7..34fd11c9f1 100644 --- a/evennia/utils/text2html.py +++ b/evennia/utils/text2html.py @@ -308,7 +308,7 @@ class TextToHTMLparser(object): elif cdict["lineend"]: return "
" elif cdict["tab"]: - text = cdict["tab"].replace("\t", " " * self.tabstop) + text = cdict["tab"].replace("\t", " ") return text elif cdict["space"] or cdict["spacestart"]: text = cdict["space"] diff --git a/evennia/web/webclient/static/webclient/css/webclient.css b/evennia/web/webclient/static/webclient/css/webclient.css index 0ce0997c56..bc94b84ae8 100644 --- a/evennia/web/webclient/static/webclient/css/webclient.css +++ b/evennia/web/webclient/static/webclient/css/webclient.css @@ -27,7 +27,6 @@ body { } } - a:link, a:visited { color: inherit; } a:hover, a:active { color: inherit; font-weight: bold;} @@ -92,6 +91,12 @@ div {margin:0px;} background-color: #333; } +.tabspace { + white-space: pre; + tab-size: 4; + -moz-tab-size: 4; +} + /* Container surrounding entire client */ #clientwrapper { height: 100%; From 0fbffd796265c3754e06c219eeca2835ca2a0f2a Mon Sep 17 00:00:00 2001 From: Griatch Date: Tue, 10 Nov 2020 19:26:02 +0100 Subject: [PATCH 05/17] Update docs --- docs/source/Evennia-API.md | 7 +++---- docs/source/toc.md | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/source/Evennia-API.md b/docs/source/Evennia-API.md index e96df0446c..a227927d5f 100644 --- a/docs/source/Evennia-API.md +++ b/docs/source/Evennia-API.md @@ -60,8 +60,8 @@ The flat API is defined in `__init__.py` [viewable here](github:evennia/__init__ - [evennia.Command](api:evennia.commands.command#evennia.commands.command.Command) - base [Command](./Commands) class. See also `evennia.default_cmds.MuxCommand` - [evennia.CmdSet](api:evennia.commands.cmdset#evennia.commands.cmdset.CmdSet) - base [Cmdset](./Command-Sets) class -- [evennia.default_cmds](api:Default-Command-Help) - access all default command classes as properties -- [evennia.syscmdkeys](api:Commands#System-Commands) - access system command keys as properties +- evennia.default_cmds - access to all [default command classes](api:evennia.commands.default) as properties +- evennia.syscmdkeys - access to all [system command](./Commands#system-commands) names as properties ### Utilities @@ -94,5 +94,4 @@ The flat API is defined in `__init__.py` [viewable here](github:evennia/__init__ ### Contributions -- [evennia.contrib](https://github.com/evennia/evennia/blob/master/evennia/contrib/) - -game-specific contributions and plugins ([docs](https://github.com/evennia/evennia/blob/master/evennia/contrib/README.md)) +- [evennia.contrib](api:evennia.contrib) - game-specific contributions and plugins ([README](github:evennia/contrib/README.md)) diff --git a/docs/source/toc.md b/docs/source/toc.md index 9e0e45f859..e9cdc2363b 100644 --- a/docs/source/toc.md +++ b/docs/source/toc.md @@ -1,5 +1,5 @@ # Toc -- [API root](api/evennia-api.rst) + - [./A voice operated elevator using events](./A-voice-operated-elevator-using-events) - [./API refactoring](./API-refactoring) - [./Accounts](./Accounts) From 43e2b0aba32a598f77a87bc21159315c90f9f183 Mon Sep 17 00:00:00 2001 From: Griatch Date: Tue, 10 Nov 2020 19:48:18 +0100 Subject: [PATCH 06/17] Update docs with better markup --- docs/source/Builder-Docs.md | 3 +- docs/source/Client-Support-Grid.md | 159 ++++++++++++++----------- docs/source/Contributing-Docs.md | 30 ++--- docs/source/_templates/versioning.html | 1 + 4 files changed, 104 insertions(+), 89 deletions(-) diff --git a/docs/source/Builder-Docs.md b/docs/source/Builder-Docs.md index f900b008ae..48331464ab 100644 --- a/docs/source/Builder-Docs.md +++ b/docs/source/Builder-Docs.md @@ -4,7 +4,7 @@ This section contains information useful to world builders. ### Building basics -- [Default in-game commands](./Default-Command-Help) +- [Default in-game commands](api:evennia.commands.default) - [Building Quick-start](./Building-Quickstart) - [Giving build permissions to others](./Building-Permissions) - [Adding text tags](./TextTags) @@ -29,7 +29,6 @@ This section contains information useful to world builders. ```toctree:: :hidden: - Default-Command-Help Building-Quickstart Building-Permissions TextTags diff --git a/docs/source/Client-Support-Grid.md b/docs/source/Client-Support-Grid.md index 63e18f89b6..1a9fc0ef61 100644 --- a/docs/source/Client-Support-Grid.md +++ b/docs/source/Client-Support-Grid.md @@ -1,94 +1,109 @@ # Client Support Grid -This grid tries to gather Evennia-specific knowledge about the various clients and protocols used. -Everyone's welcome to report their findings. +This grid tries to gather info about different MU clients when used with Evennia. +If you want to report a problem, update an entry or add a client, make a +new [documentation issue](github:issue) for it. Everyone's encouraged to report their findings. -##### Legend: +##### Legend: - - **Name**: The name of the client. If it's only available for a specific OS, it should be noted -here too. + - **Name**: The name of the client. Also note if it's OS-specific. - **Version**: Which version or range of client versions were tested. - - **Comments**: Any comments or quirks on using this client with Evennia should be added here. Also -note if some other protocol than Telnet is used (like Websockets, SSH etc). + - **Comments**: Any quirks on using this client with Evennia should be added here. ## Client Grid -Name | Version | Comments -:----------:------------ -[Evennia webclient][1] | 0.6 | Uses WS/AJAX. [Current client issues][2] -[tintin++][3] | 2.0+ | No MXP support -[tinyfugue][4] | 5.0+ | No UTF-8 support -[MUSHclient][5] (Win) | 4.94 | NAWS reports full text area -[Zmud][6] (Win) | 7.21 | *UNTESTED* -[Cmud][7] (Win) | v3 | *UNTESTED* -[Potato][8] | 2.0.0b16 | No MXP, MCCP support. Win 32bit does not understand -"localhost", must use `127.0.0.1`. [Newline issue](https://github.com/evennia/evennia/issues/1131). -*Won't send a single blank line on Enter press. -[Mudlet][9] | 3.4+ | No known issues. Some older versions showed <> as html under MXP. -[SimpleMU][10] (Win) | full | *UNTESTED*. Discontinued. NAWS reports pixel size. -[Atlantis][11] (Mac) | 0.9.9.4 | No known issues. -[GMUD][12] | 0.0.1 | Can't handle any telnet handshakes. Not recommended. -[BeipMU][13] (Win) | 3.0.255 | No MXP support. Best to enable "MUD prompt handling", disable -"Handle HTML tags". -[MudRammer][14] (IOS) | 1.8.7 | Bad Telnet Protocol compliance: displays spurious characters. -[MUDMaster][15] (IOS) | 1.3.1 | *UNTESTED* -[BlowTorch][16] (Andr) | 1.1.3 | *Telnet NOP displays as spurious character. -[Mukluk][17] (Andr) | 2015.11.20| *Telnet NOP displays as spurious character. Has UTF-8/Emoji -support. -[Gnome-MUD][18] (Unix) | 0.11.2 | Telnet handshake errors. First (only) attempt at logging in -fails. -[Spyrit][19] | 0.4 | No MXP, OOB support. -[JamochaMUD][20] | 5.2 | Does not support ANSI within MXP text. -[DuckClient][21] (Chrome)| 4.2 | No MXP support. Displays Telnet Go-Ahead and WILL SUPPRESS-GO-AHEAD -as ù character. Also seems to run the `version` command on connection, which will not work in -`MULTISESSION_MODES` above 1. -[KildClient][22] | 2.11.1 | No known issues. +```eval_rst -[1]: https://github.com/evennia/evennia/wiki/Web%20features#web-client -[2]: https://github.com/evennia/evennia/issues?utf8=%E2%9C%93&q=client+status%3Dopen+] -[3]: http://tintin.sourceforge.net/ -[4]: http://tinyfugue.sourceforge.net/ -[5]: http://mushclient.com/ -[6]: http://forums.zuggsoft.com/index.php?page=4&action=file&file_id=65 -[7]: http://forums.zuggsoft.com/index.php?page=4&action=category&cat_id=11 -[8]: http://www.potatomushclient.com/ -[9]: http://www.mudlet.org/ -[10]: https://archive.org/details/tucows_196173_SimpleMU_MU_Client -[11]: http://www.riverdark.net/atlantis/ -[12]: https://sourceforge.net/projects/g-mud/ -[13]: http://www.beipmu.com/ -[14]: https://itunes.apple.com/us/app/mudrammer-a-modern-mud-client/id597157072 -[15]: https://itunes.apple.com/us/app/mudmaster/id341160033 -[16]: http://bt.happygoatstudios.com/ -[17]: https://play.google.com/store/apps/details?id=com.crap.mukluk -[18]: https://github.com/GNOME/gnome-mud -[19]: https://spyrit.ierne.eu.org/ -[20]: http://jamochamud.org/ -[21]: http://duckclient.com/ -[22]: https://www.kildclient.org/ ++----------------------------+-----------+----------------------------------------------------------------+ +| Name | Version | Comments | ++============================+===========+================================================================+ +| `Evennia Webclient`_ | 0.9 | Evennia-specific | ++----------------------------+-----------+----------------------------------------------------------------+ +| `tintin++`_ | 2.0+ | No MXP support | ++----------------------------+-----------+----------------------------------------------------------------+ +| tinyfugue_ | 5.0+ | No UTF-8 support | ++----------------------------+-----------+----------------------------------------------------------------+ +| MUSHclient_ (Win) | 4.94 | NAWS reports full text area | ++----------------------------+-----------+----------------------------------------------------------------+ +| Zmud_ (Win) | 7.21 | *UNTESTED* | ++----------------------------+-----------+----------------------------------------------------------------+ +| Cmud_ (Win) | v3 | *UNTESTED* | ++----------------------------+-----------+----------------------------------------------------------------+ +| Potato_ | 2.0.0b16 | No MXP, MCCP support. Win 32bit does not understand | +| | | "localhost", must use `127.0.0.1`. | ++----------------------------+-----------+----------------------------------------------------------------+ +| Mudlet_ | 3.4+ | No known issues. Some older versions showed <> as html | +| | | under MXP. | ++----------------------------+-----------+----------------------------------------------------------------+ +| SimpleMU_ (Win) | full | Discontinued. NAWS reports pixel size. | ++----------------------------+-----------+----------------------------------------------------------------+ +| Atlantis_ (Mac) | 0.9.9.4 | No known issues. | ++----------------------------+-----------+----------------------------------------------------------------+ +| GMUD_ | 0.0.1 | Can't handle any telnet handshakes. Not recommended. | ++----------------------------+-----------+----------------------------------------------------------------+ +| BeipMU_ (Win) | 3.0.255 | No MXP support. Best to enable "MUD prompt handling", disable | +| | | "Handle HTML tags". | ++----------------------------+-----------+----------------------------------------------------------------+ +| MudRammer_ (IOS) | 1.8.7 | Bad Telnet Protocol compliance: displays spurious characters. | ++----------------------------+-----------+----------------------------------------------------------------+ +| MUDMaster_ | 1.3.1 | *UNTESTED* | ++----------------------------+-----------+----------------------------------------------------------------+ +| BlowTorch_ (Andr) | 1.1.3 | Telnet NOP displays as spurious character. | ++----------------------------+-----------+----------------------------------------------------------------+ +| Mukluk_ (Andr) | 2015.11.20| Telnet NOP displays as spurious character. Has UTF-8/Emoji | +| | | support. | ++----------------------------+-----------+----------------------------------------------------------------+ +| Gnome-MUD_ (Unix) | 0.11.2 | Telnet handshake errors. First (only) attempt at logging in | +| | | fails. | ++----------------------------+-----------+----------------------------------------------------------------+ +| Spyrit_ | 0.4 | No MXP, OOB support. | ++----------------------------+-----------+----------------------------------------------------------------+ +| JamochaMUD_ | 5.2 | Does not support ANSI within MXP text. | ++----------------------------+-----------+----------------------------------------------------------------+ +| DuckClient_ (Chrome) | 4.2 | No MXP support. Displays Telnet Go-Ahead and | +| | | WILL SUPPRESS-GO-AHEAD as ù character. Also seems to run | +| | | the `version` command on connection, which will not work in | +| | | `MULTISESSION_MODES` above 1. | ++----------------------------+-----------+----------------------------------------------------------------+ +| KildClient_ | 2.11.1 | No known issues. | ++----------------------------+-----------+----------------------------------------------------------------+ +.. _Evennia Webclient: ../Components/Webclient.html +.. _tintin++: http://tintin.sourceforge.net/ +.. _tinyfugue: http://tinyfugue.sourceforge.net/ +.. _MUSHclient: http://mushclient.com/ +.. _Zmud: http://forums.zuggsoft.com/index.php?page=4&action=file&file_id=65 +.. _Cmud: http://forums.zuggsoft.com/index.php?page=4&action=category&cat_id=11 +.. _Potato: http://www.potatomushclient.com/ +.. _Mudlet: http://www.mudlet.org/ +.. _SimpleMU: https://archive.org/details/tucows_196173_SimpleMU_MU_Client +.. _Atlantis: http://www.riverdark.net/atlantis/ +.. _GMUD: https://sourceforge.net/projects/g-mud/ +.. _BeipMU: http://www.beipmu.com/ +.. _MudRammer: https://itunes.apple.com/us/app/mudrammer-a-modern-mud-client/id597157072 +.. _MUDMaster: https://itunes.apple.com/us/app/mudmaster/id341160033 +.. _BlowTorch: http://bt.happygoatstudios.com/ +.. _Mukluk: https://play.google.com/store/apps/details?id=com.crap.mukluk +.. _Gnome-MUD: https://github.com/GNOME/gnome-mud +.. _Spyrit: https://spyrit.ierne.eu.org/ +.. _JamochaMUD: http://jamochamud.org/ +.. _DuckClient: http://duckclient.com/ +.. _KildClient: https://www.kildclient.org/ + +``` ## Workarounds for client issues: ### Issue: Telnet NOP displays as spurious character. Known clients: -* [BlowTorch][16](Andr) -* [Mukluk][17](Andr) +* BlowTorch (Andr) +* Mukluk (Andr) Workaround: -* Set the command in game to `@option NOPKEEPALIVE=off` for the session, or use the `/save` -parameter to disable it for that Evennian account permanently. +* In-game: Use `@option NOPKEEPALIVE=off` for the session, or use the `/save` +parameter to disable it for that Evennia account permanently. * Client-side: Set a gag-type trigger on the NOP character to make it invisible to the client. -### Issue: Won't send blank line on Enter key press. - -Known clients: - -* [Potato][8] - -Workaround: - -* Press Control Enter, then Enter key again to send blank line. diff --git a/docs/source/Contributing-Docs.md b/docs/source/Contributing-Docs.md index 638b04a3b9..491c09eb51 100644 --- a/docs/source/Contributing-Docs.md +++ b/docs/source/Contributing-Docs.md @@ -2,7 +2,7 @@ ```warning:: - WARNING: This system is still WIP and many things are bound to change! + The creation of docs pages is still WIP and we are still figuring things out here and there. ``` Contributing to the docs is is like [contributing to the rest of Evennia][contributing]: Check out the branch of Evennia you want to edit the documentation for. Create your @@ -643,7 +643,7 @@ a good idea to end with four dashes `----`. This will create a visible line betw class/function docs to follow. See for example [the Traits docs](api:evennia.contrib.traits). All non-private classes, methods and functions must have a Google-style docstring, as per the -[Evennia coding style guidelines][github:evennia/CODING_STYLE.md]. This will then be correctly formatted +[Evennia coding style guidelines](github:evennia/CODING_STYLE.md). This will then be correctly formatted into pretty api docs. ## Technical @@ -661,19 +661,19 @@ extension to understand our friendly Google-style docstrings used in classes and functions etc. -[sphinx](https://www.sphinx-doc.org/en/master/) -[recommonmark](https://recommonmark.readthedocs.io/en/latest/index.html) -[commonmark](https://spec.commonmark.org/current/) -[commonmark-help](https://commonmark.org/help/) -[sphinx-autodoc](http://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#module-sphinx.ext.autodoc) -[sphinx-napoleon](http://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html) +[sphinx]: https://www.sphinx-doc.org/en/master/ +[recommonmark]: https://recommonmark.readthedocs.io/en/latest/index.html +[commonmark]: https://spec.commonmark.org/current/ +[commonmark-help]: https://commonmark.org/help/ +[sphinx-autodoc]: http://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#module-sphinx.ext.autodoc +[sphinx-napoleon]: http://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html [getting-started]: Setup/Setup-Quickstart [contributing]: ./Contributing -[ReST](https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html) -[ReST-tables](https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html#tables) -[ReST-directives](https://www.sphinx-doc.org/en/master/usage/restruturedtext/directives.html) -[Windows-WSL](https://docs.microsoft.com/en-us/windows/wsl/install-win10) +[ReST]: https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html +[ReST-tables]: https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html#tables +[ReST-directives]: https://www.sphinx-doc.org/en/master/usage/restruturedtext/directives.html +[Windows-WSL]: https://docs.microsoft.com/en-us/windows/wsl/install-win10 [linkdemo]: #Links -[retext](https://github.com/retext-project/retext) -[grip](https://github.com/joeyespo/grip) -[pycharm](https://www.jetbrains.com/pycharm/) +[retext]: https://github.com/retext-project/retext +[grip]: https://github.com/joeyespo/grip +[pycharm]: https://www.jetbrains.com/pycharm/ diff --git a/docs/source/_templates/versioning.html b/docs/source/_templates/versioning.html index 02eaef1396..c035b0c97e 100644 --- a/docs/source/_templates/versioning.html +++ b/docs/source/_templates/versioning.html @@ -5,4 +5,5 @@
  • {{ item.release }} ({{ item.name }} branch)
  • {%- endfor %} + {% endif %} From 4dd2e71448101a98d31ba3bc45e167083aed222f Mon Sep 17 00:00:00 2001 From: Griatch Date: Tue, 10 Nov 2020 22:54:09 +0100 Subject: [PATCH 07/17] Fix traceback in MULTISESSION_MODE=3 for empty ic. Resolves #2250 --- evennia/commands/default/account.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evennia/commands/default/account.py b/evennia/commands/default/account.py index f013e79c60..ae284a6c85 100644 --- a/evennia/commands/default/account.py +++ b/evennia/commands/default/account.py @@ -304,7 +304,7 @@ class CmdIC(COMMAND_DEFAULT_CLASS): character_candidates = [] if not self.args: - character_candidates = [account.db._last_puppet] or [] + character_candidates = [account.db._last_puppet] if account.db._last_puppet else [] if not character_candidates: self.msg("Usage: ic ") return From b7b2872f43a890e11df6269d281b7c5209541c71 Mon Sep 17 00:00:00 2001 From: Griatch Date: Wed, 11 Nov 2020 00:41:58 +0100 Subject: [PATCH 08/17] Fix profunc parse and html tabs. Resolve #2246 --- evennia/prototypes/prototypes.py | 5 ++++- evennia/utils/tests/test_text2html.py | 14 +++++++------- evennia/utils/text2html.py | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/evennia/prototypes/prototypes.py b/evennia/prototypes/prototypes.py index 35122f68fc..e2c39d5700 100644 --- a/evennia/prototypes/prototypes.py +++ b/evennia/prototypes/prototypes.py @@ -929,7 +929,10 @@ def init_spawn_value(value, validator=None): value = validator(value[0](*make_iter(args))) else: value = validator(value) - return protfunc_parser(value) + result = protfunc_parser(value) + if result != value: + return validator(result) + return result def value_to_obj_or_any(value): diff --git a/evennia/utils/tests/test_text2html.py b/evennia/utils/tests/test_text2html.py index 9e331f630d..0bb151f22b 100644 --- a/evennia/utils/tests/test_text2html.py +++ b/evennia/utils/tests/test_text2html.py @@ -156,7 +156,7 @@ class TestText2Html(TestCase): "tab": "\t", "space": "", } - self.assertEqual("  ", parser.sub_text(mocked_match)) + self.assertEqual("  ", parser.sub_text(mocked_match)) mocked_match.groupdict.return_value = { "htmlchars": "", @@ -165,7 +165,7 @@ class TestText2Html(TestCase): "space": " ", "spacestart": " ", } - self.assertEqual("    ", + self.assertEqual("    ", parser.sub_text(mocked_match)) mocked_match.groupdict.return_value = { @@ -182,16 +182,16 @@ class TestText2Html(TestCase): parser = text2html.HTML_PARSER parser.tabstop = 4 # single tab - self.assertEqual(parser.parse("foo|-foo"), - "foo    foo") + self.assertEqual(parser.parse("foo|>foo"), + "foo    foo") # space and tab - self.assertEqual(parser.parse("foo |-foo"), + self.assertEqual(parser.parse("foo |>foo"), "foo     foo") # space, tab, space - self.assertEqual(parser.parse("foo |- foo"), - "foo      foo") + self.assertEqual(parser.parse("foo |> foo"), + "foo      foo") def test_parse_space_to_html(self): """test space parsing - a single space should be kept, two or more diff --git a/evennia/utils/text2html.py b/evennia/utils/text2html.py index 34fd11c9f1..7fb19a8ab8 100644 --- a/evennia/utils/text2html.py +++ b/evennia/utils/text2html.py @@ -308,7 +308,7 @@ class TextToHTMLparser(object): elif cdict["lineend"]: return "
    " elif cdict["tab"]: - text = cdict["tab"].replace("\t", " ") + text = cdict["tab"].replace("\t", " " + " " * (self.tabstop - 1)) return text elif cdict["space"] or cdict["spacestart"]: text = cdict["space"] From 126dd135cb2794e59c5c40bb5f9f4f58156ca27b Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 12 Nov 2020 20:46:53 +0100 Subject: [PATCH 09/17] Fix an inconsistency in category-refresh for empty string, related to #2236 --- evennia/typeclasses/attributes.py | 9 +++-- evennia/utils/create.py | 7 ++-- evennia/utils/tests/test_create_functions.py | 39 ++++++++++++++++++++ 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/evennia/typeclasses/attributes.py b/evennia/typeclasses/attributes.py index 99a897f275..26bbeff04a 100644 --- a/evennia/typeclasses/attributes.py +++ b/evennia/typeclasses/attributes.py @@ -181,10 +181,10 @@ class Attribute(SharedMemoryModel): # def __str__(self): - return smart_str("%s(%s)" % (self.db_key, self.id)) + return smart_str("%s[category=%s](#%s)" % (self.db_key, self.db_category, self.id)) def __repr__(self): - return "%s(%s)" % (self.db_key, self.id) + return "%s[category=%s](#%s)" % (self.db_key, self.db_category, self.id) def access(self, accessing_obj, access_type="attrread", default=False, **kwargs): """ @@ -257,7 +257,7 @@ class AttributeHandler(object): "%s-%s" % ( to_str(attr.db_key).lower(), - attr.db_category.lower() if attr.db_category else None, + attr.db_category.lower() if attr.db_category is not None else None, ), attr, ) @@ -289,7 +289,7 @@ class AttributeHandler(object): """ key = key.strip().lower() if key else None - category = category.strip().lower() if category else None + category = category.strip().lower() if category is not None else None if key: cachekey = "%s-%s" % (key, category) cachefound = False @@ -558,6 +558,7 @@ class AttributeHandler(object): return category = category.strip().lower() if category is not None else None + keystr = key.strip().lower() attr_obj = self._getcache(key, category) diff --git a/evennia/utils/create.py b/evennia/utils/create.py index 9adce45289..e6066d1191 100644 --- a/evennia/utils/create.py +++ b/evennia/utils/create.py @@ -96,7 +96,7 @@ def create_object( location itself or during unittests. attributes (list): Tuples on the form (key, value) or (key, value, category), (key, value, lockstring) or (key, value, lockstring, default_access). - to set as Attributes on the new object. + to set as Attributes on the new object. nattributes (list): Non-persistent tuples on the form (key, value). Note that adding this rarely makes sense since this data will not survive a reload. @@ -229,8 +229,9 @@ def create_script( report_to (Object): The object to return error messages to. desc (str): Optional description of script tags (list): List of tags or tuples (tag, category). - attributes (list): List if tuples (key, value) or (key, value, category) - (key, value, lockstring) or (key, value, lockstring, default_access). + attributes (list): List of tuples `(key, value)`, `(key, value, category)`, + `(key, value, category, lockstring)` or + `(key, value, category, lockstring, default_access)`. Returns: script (obj): An instance of the script created diff --git a/evennia/utils/tests/test_create_functions.py b/evennia/utils/tests/test_create_functions.py index c9ae5b2cb7..10f9892219 100644 --- a/evennia/utils/tests/test_create_functions.py +++ b/evennia/utils/tests/test_create_functions.py @@ -78,6 +78,45 @@ class TestCreateScript(EvenniaTest): assert script.key == "test_script" script.stop() + def test_attr_creation_func(self): + """ + Test of assigning attributes during creation + + """ + attrvalue = {'test1': 1, 'test2': 'boo'} + + # creation-function direct call + script = create.create_script( + key='script_broken', + attributes=[ + ('testname', attrvalue, '') + ] + ) + self.assertTrue(script) + self.assertEqual(script.db.testname, None) # since the category is '' and not None + self.assertEqual(script.attributes.get("testname", category=''), attrvalue) + script.stop() + + def test_attr_method_creation_malformed(self): + """ + Adding the wrong type for one attribute-tuple element + + """ + attrvalue = {'test1': 1, 'test2': 'boo'} + + # method-based creation + script, err = DefaultScript.create( + 'scripttest2', + attributes=[ + # test of wrong syntax - last element should be bool + ('testname', attrvalue, None, '', '') + ] + ) + self.assertFalse(err) + self.assertTrue(script) + self.assertEqual(script.db.testname, attrvalue) + script.stop() + class TestCreateHelpEntry(TestCase): From e4b1e1c9aa80febb54daf5728508570d39ac0f6a Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 12 Nov 2020 22:01:24 +0100 Subject: [PATCH 10/17] Better handle error when trying to add ticker with subsecond interval. Resolves #2235 --- evennia/scripts/tickerhandler.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/evennia/scripts/tickerhandler.py b/evennia/scripts/tickerhandler.py index 021522ae21..fa51e342d1 100644 --- a/evennia/scripts/tickerhandler.py +++ b/evennia/scripts/tickerhandler.py @@ -80,9 +80,15 @@ _SA = object.__setattr__ _ERROR_ADD_TICKER = """TickerHandler: Tried to add an invalid ticker: -{storekey} +{store_key} Ticker was not added.""" +_ERROR_ADD_TICKER_SUB_SECOND = """You are trying to add a ticker running faster +than once per second. This is not supported and also probably not useful: +Spamming messages to the user faster than once per second serves no purpose in +a text-game, and if you want to update some property, consider doing so +on-demand rather than using a ticker. +""" class Ticker(object): """ @@ -359,7 +365,8 @@ class TickerHandler(object): obj (Object, tuple or None): Subscribing object if any. If a tuple, this is a packed_obj tuple from dbserialize. path (str or None): Python-path to callable, if any. - interval (int): Ticker interval. + interval (int): Ticker interval. Floats will be converted to + nearest lower integer value. callfunc (callable or str): This is either the callable function or the name of the method to call. Note that the callable is never stored in the key; that is uniquely identified with the python-path. @@ -378,6 +385,9 @@ class TickerHandler(object): `idstring` and `persistent` are integers, strings and bools respectively. """ + if interval < 1: + raise RuntimeError(_ERROR_ADD_TICKER_SUB_SECOND) + interval = int(interval) persistent = bool(persistent) packed_obj = pack_dbobj(obj) From 3bee981cffcb1cd50192e5a9cfe3ea0910641b23 Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 12 Nov 2020 22:28:14 +0100 Subject: [PATCH 11/17] Delay import of module-prototypes to avoid init-clash. Resolves #2232. --- evennia/__init__.py | 6 ++- evennia/prototypes/prototypes.py | 64 +++++++++++++++++--------------- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/evennia/__init__.py b/evennia/__init__.py index 4bb82ebaf2..828bec77fe 100644 --- a/evennia/__init__.py +++ b/evennia/__init__.py @@ -392,8 +392,12 @@ def _init(): BASE_GUEST_TYPECLASS = class_from_module(settings.BASE_GUEST_TYPECLASS) del class_from_module - # delayed starts + # delayed starts - important so as to not back-access evennia before it has + # finished initializing GLOBAL_SCRIPTS.start() + from .prototypes import prototypes + prototypes.load_module_prototypes() + del prototypes def set_trace(term_size=(140, 80), debugger="auto"): diff --git a/evennia/prototypes/prototypes.py b/evennia/prototypes/prototypes.py index e2c39d5700..185b9dfc5d 100644 --- a/evennia/prototypes/prototypes.py +++ b/evennia/prototypes/prototypes.py @@ -144,35 +144,41 @@ def homogenize_prototype(prototype, custom_keys=None): # module-based prototypes -for mod in settings.PROTOTYPE_MODULES: - # to remove a default prototype, override it with an empty dict. - # internally we store as (key, desc, locks, tags, prototype_dict) - prots = [] - for variable_name, prot in all_from_module(mod).items(): - if isinstance(prot, dict): - if "prototype_key" not in prot: - prot["prototype_key"] = variable_name.lower() - prots.append((prot["prototype_key"], homogenize_prototype(prot))) - # assign module path to each prototype_key for easy reference - _MODULE_PROTOTYPE_MODULES.update({prototype_key.lower(): mod for prototype_key, _ in prots}) - # make sure the prototype contains all meta info - for prototype_key, prot in prots: - actual_prot_key = prot.get("prototype_key", prototype_key).lower() - prot.update( - { - "prototype_key": actual_prot_key, - "prototype_desc": prot["prototype_desc"] if "prototype_desc" in prot else mod, - "prototype_locks": ( - prot["prototype_locks"] - if "prototype_locks" in prot - else "use:all();edit:false()" - ), - "prototype_tags": list( - set(list(make_iter(prot.get("prototype_tags", []))) + ["module"]) - ), - } - ) - _MODULE_PROTOTYPES[actual_prot_key] = prot +def load_module_prototypes(): + """ + This is called by `evennia.__init__` as Evennia initializes. It's important + to do this late so as to not interfere with evennia initialization. + + """ + for mod in settings.PROTOTYPE_MODULES: + # to remove a default prototype, override it with an empty dict. + # internally we store as (key, desc, locks, tags, prototype_dict) + prots = [] + for variable_name, prot in all_from_module(mod).items(): + if isinstance(prot, dict): + if "prototype_key" not in prot: + prot["prototype_key"] = variable_name.lower() + prots.append((prot["prototype_key"], homogenize_prototype(prot))) + # assign module path to each prototype_key for easy reference + _MODULE_PROTOTYPE_MODULES.update({prototype_key.lower(): mod for prototype_key, _ in prots}) + # make sure the prototype contains all meta info + for prototype_key, prot in prots: + actual_prot_key = prot.get("prototype_key", prototype_key).lower() + prot.update( + { + "prototype_key": actual_prot_key, + "prototype_desc": prot["prototype_desc"] if "prototype_desc" in prot else mod, + "prototype_locks": ( + prot["prototype_locks"] + if "prototype_locks" in prot + else "use:all();edit:false()" + ), + "prototype_tags": list( + set(list(make_iter(prot.get("prototype_tags", []))) + ["module"]) + ), + } + ) + _MODULE_PROTOTYPES[actual_prot_key] = prot # Db-based prototypes From 8356c8f901e6142ddcf43acf41c104625b853056 Mon Sep 17 00:00:00 2001 From: Griatch Date: Thu, 12 Nov 2020 23:23:28 +0100 Subject: [PATCH 12/17] Fix .obj transfer for nested cmdset. Resolves #2221. --- evennia/commands/cmdset.py | 17 +++++++++-------- evennia/commands/tests.py | 25 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/evennia/commands/cmdset.py b/evennia/commands/cmdset.py index fe7812aaa9..faf4cf61a6 100644 --- a/evennia/commands/cmdset.py +++ b/evennia/commands/cmdset.py @@ -518,15 +518,16 @@ class CmdSet(object, metaclass=_CmdSetMeta): # cmd is a command set so merge all commands in that set # to this one. We raise a visible error if we created # an infinite loop (adding cmdset to itself somehow) + cmdset = cmd try: - cmd = self._instantiate(cmd) + cmdset = self._instantiate(cmdset) except RuntimeError: - string = "Adding cmdset %(cmd)s to %(class)s lead to an " - string += "infinite loop. When adding a cmdset to another, " - string += "make sure they are not themself cyclically added to " - string += "the new cmdset somewhere in the chain." - raise RuntimeError(_(string) % {"cmd": cmd, "class": self.__class__}) - cmds = cmd.commands + err = ("Adding cmdset {cmdset} to {cls} lead to an " + "infinite loop. When adding a cmdset to another, " + "make sure they are not themself cyclically added to " + "the new cmdset somewhere in the chain.") + raise RuntimeError(_(err.format(cmdset=cmdset, cls=self.__class__))) + cmds = cmdset.commands elif is_iter(cmd): cmds = [self._instantiate(c) for c in cmd] else: @@ -535,7 +536,7 @@ class CmdSet(object, metaclass=_CmdSetMeta): system_commands = self.system_commands for cmd in cmds: # add all commands - if not hasattr(cmd, "obj"): + if not hasattr(cmd, "obj") or cmd.obj is None: cmd.obj = self.cmdsetobj try: ic = commands.index(cmd) diff --git a/evennia/commands/tests.py b/evennia/commands/tests.py index 88e4616d9e..100d9a7b06 100644 --- a/evennia/commands/tests.py +++ b/evennia/commands/tests.py @@ -1199,3 +1199,28 @@ class TestCmdParser(TestCase): cmdparser.cmdparser("test1hello", a_cmdset, None), [("test1", "hello", bcmd, 5, 0.5, "test1")], ) + + +class TestCmdSetNesting(EvenniaTest): + """ + Test 'nesting' of cmdsets by adding + """ + + def test_nest(self): + + class CmdA(Command): + key = "a" + + def func(self): + self.msg(str(self.obj)) + + class CmdSetA(CmdSet): + def at_cmdset_creation(self): + self.add(CmdA) + + class CmdSetB(CmdSet): + def at_cmdset_creation(self): + self.add(CmdSetA) + + cmd = self.char1.cmdset.cmdset_stack[-1].commands[0] + self.assertEqual(cmd.obj, self.char1) From 975e98766e44595c9d8ba1ebcb07f469ccc17261 Mon Sep 17 00:00:00 2001 From: Griatch Date: Fri, 13 Nov 2020 20:39:44 +0100 Subject: [PATCH 13/17] Better handle multimatch index out of scope. Resolve #2207. --- evennia/commands/cmdparser.py | 9 +++++++-- evennia/objects/manager.py | 11 ++++++----- evennia/objects/objects.py | 3 ++- evennia/server/portal/telnet.py | 1 - 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/evennia/commands/cmdparser.py b/evennia/commands/cmdparser.py index 56b702d8c1..72040472e4 100644 --- a/evennia/commands/cmdparser.py +++ b/evennia/commands/cmdparser.py @@ -209,10 +209,15 @@ def cmdparser(raw_string, cmdset, caller, match_index=None): quality = [mat[4] for mat in matches] matches = matches[-quality.count(quality[-1]) :] - if len(matches) > 1 and match_index is not None and 0 < match_index <= len(matches): + if len(matches) > 1 and match_index is not None: # We couldn't separate match by quality, but we have an # index argument to tell us which match to use. - matches = [matches[match_index - 1]] + if 0 < match_index <= len(matches): + matches = [matches[match_index - 1]] + else: + # we tried to give an index outside of the range - this means + # a no-match + matches = [] # no matter what we have at this point, we have to return it. return matches diff --git a/evennia/objects/manager.py b/evennia/objects/manager.py index d29ca9a739..0a3dbc90fa 100644 --- a/evennia/objects/manager.py +++ b/evennia/objects/manager.py @@ -466,7 +466,6 @@ class ObjectDBManager(TypedObjectManager): # strips the number match_number, searchdata = match.group("number"), match.group("name") match_number = int(match_number) - 1 - match_number = match_number if match_number >= 0 else None if match_number is not None or not exact: # run search again, with the exactness set by call matches = _searcher(searchdata, candidates, typeclass, exact=exact) @@ -474,11 +473,13 @@ class ObjectDBManager(TypedObjectManager): # deal with result if len(matches) > 1 and match_number is not None: # multiple matches, but a number was given to separate them - try: + if 0 <= match_number < len(matches): + # limit to one match matches = [matches[match_number]] - except IndexError: - # match number not matching anything - pass + else: + # a number was given outside of range. This means a no-match. + matches = [] + # return a list (possibly empty) return matches diff --git a/evennia/objects/objects.py b/evennia/objects/objects.py index 542a89997b..8b66bce8f8 100644 --- a/evennia/objects/objects.py +++ b/evennia/objects/objects.py @@ -389,7 +389,8 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase): a global search. - `me,self`: self-reference to this object - `-` - can be used to differentiate - between multiple same-named matches + between multiple same-named matches. The exact form of this input + is given by `settings.SEARCH_MULTIMATCH_REGEX`. global_search (bool): Search all objects globally. This overrules 'location' data. use_nicks (bool): Use nickname-replace (nicktype "object") on `searchdata`. typeclass (str or Typeclass, or list of either): Limit search only diff --git a/evennia/server/portal/telnet.py b/evennia/server/portal/telnet.py index 70a3b815ef..821e96aa24 100644 --- a/evennia/server/portal/telnet.py +++ b/evennia/server/portal/telnet.py @@ -85,7 +85,6 @@ class TelnetProtocol(Telnet, StatefulTelnetProtocol, Session): super().dataReceived(data) except ValueError as err: from evennia.utils import logger - logger.log_err(f"Malformed telnet input: {err}") def connectionMade(self): From 307716a4cdd7a2ebd6dd6d637cf91ea84729dda5 Mon Sep 17 00:00:00 2001 From: Griatch Date: Fri, 13 Nov 2020 20:59:49 +0100 Subject: [PATCH 14/17] Don't allow 3-box with only two boxes in room. Resolve #2206. --- CHANGELOG.md | 2 ++ evennia/objects/manager.py | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54a08b5941..3855deceb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -83,6 +83,8 @@ without arguments starts a full interactive Python console. - New EvMenu templating system for quickly building simpler EvMenus without as much code. - Add `Command.client_height()` method to match existing `.client_width` (stricako) - Include more Web-client info in `session.protocol_flags`. +- Fixes in multi-match situations - don't allow finding/listing multimatches for 3-box when + only two boxes in location. ## Evennia 0.9 (2018-2019) diff --git a/evennia/objects/manager.py b/evennia/objects/manager.py index 0a3dbc90fa..2286f784c5 100644 --- a/evennia/objects/manager.py +++ b/evennia/objects/manager.py @@ -471,7 +471,12 @@ class ObjectDBManager(TypedObjectManager): matches = _searcher(searchdata, candidates, typeclass, exact=exact) # deal with result - if len(matches) > 1 and match_number is not None: + if len(matches) == 1 and match_number is not None and match_number != 0: + # this indicates trying to get a single match with a match-number + # targeting some higher-number match (like 2-box when there is only + # one box in the room). This leads to a no-match. + matches = [] + elif len(matches) > 1 and match_number is not None: # multiple matches, but a number was given to separate them if 0 <= match_number < len(matches): # limit to one match From 815c82607c602e04cc17f2c592b019b2431d018e Mon Sep 17 00:00:00 2001 From: Griatch Date: Fri, 13 Nov 2020 22:52:50 +0100 Subject: [PATCH 15/17] Minor fix for logging --- evennia/utils/logger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evennia/utils/logger.py b/evennia/utils/logger.py index 8785c1319c..7997327ab0 100644 --- a/evennia/utils/logger.py +++ b/evennia/utils/logger.py @@ -367,7 +367,7 @@ class EvenniaLogFile(logfile.LogFile): logfile.LogFile.rotate(self) return lines = tail_log_file(self.path, 0, self.num_lines_to_append) - logfile.LogFile.rotate(self) + super().rotate() for line in lines: self.write(line) From 43845560c5f4dfbe0e60d02f157a82821fb5a40b Mon Sep 17 00:00:00 2001 From: Griatch Date: Sat, 14 Nov 2020 13:38:06 +0100 Subject: [PATCH 16/17] Change build sourse for master --- docs/source/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index f476128d8c..14ee089c06 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -53,7 +53,7 @@ html_static_path = ["_static"] # which branches to include in multi-versioned docs # - master, develop and vX.X branches -smv_branch_whitelist = r"^master$|^develop$|^v[0-9\.]+?$" +smv_branch_whitelist = r"^develop$|^v[0-9\.]+?$" smv_outputdir_format = "{config.release}" # don't make docs for tags smv_tag_whitelist = r"^$" From 61162bd4d2b221951639fd36fcdf69bbc531f9e6 Mon Sep 17 00:00:00 2001 From: Griatch Date: Sat, 14 Nov 2020 16:06:05 +0100 Subject: [PATCH 17/17] Update changelog --- CHANGELOG.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3855deceb4..d17b5c6d9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,15 @@ # Changelog -## Evennia 1.0 (2019-) (WIP) +## Evennia 1.0-dev (2019-) (WIP) - New `drop:holds()` lock default to limit dropping nonsensical things. Access check defaults to True for backwards-compatibility in 0.9, will be False in 1.0 - Add `tags.has()` method for checking if an object has a tag or tags (PR by ChrisLR) -### Evennia 0.9.5 (master) +### Evennia 0.9.5 (Nov 2020) + +A transitional release, including new doc system. + - `is_typeclass(obj (Object), exact (bool))` now defaults to exact=False - `py` command now reroutes stdout to output results in-game client. `py` without arguments starts a full interactive Python console.