diff --git a/docs/source/Components/Batch-Code-Processor.md b/docs/source/Components/Batch-Code-Processor.md index ba6ae36f57..054d44e833 100644 --- a/docs/source/Components/Batch-Code-Processor.md +++ b/docs/source/Components/Batch-Code-Processor.md @@ -91,13 +91,12 @@ Below is a version of the example file found in `evennia/contrib/tutorial_exampl table = create_object(Object, key="Blue Table", location=limbo) chair = create_object(Object, key="Blue Chair", location=limbo) - string = "A %s and %s were created." + string = f"A {table} and {chair} were created." if DEBUG: table.delete() chair.delete() - string += " Since debug was active, " \ - "they were deleted again." - caller.msg(string % (table, chair)) + string += " Since debug was active, they were deleted again." + caller.msg(string) ``` This uses Evennia's Python API to create three objects in sequence. diff --git a/docs/source/Components/Commands.md b/docs/source/Components/Commands.md index d7ed92f46b..a369371334 100644 --- a/docs/source/Components/Commands.md +++ b/docs/source/Components/Commands.md @@ -65,7 +65,7 @@ Here is a minimalistic command with no custom parsing: def func(self): # echo the caller's input back to the caller - self.caller.msg("Echo: {}".format(self.args) + self.caller.msg(f"Echo: {self.args}") ``` @@ -548,7 +548,7 @@ class CmdTestID(Command): self.xval = 0 self.xval += 1 - self.caller.msg("Command memory ID: {} (xval={})".format(id(self), self.xval)) + self.caller.msg(f"Command memory ID: {id(self)} (xval={self.xval})") ``` @@ -651,7 +651,7 @@ thus do so asynchronously, using callbacks. ```python # in command class func() def callback(ret, caller): - caller.msg("Returned is %s" % ret) + caller.msg(f"Returned is {ret}") deferred = self.execute_command("longrunning") deferred.addCallback(callback, self.caller) ``` diff --git a/docs/source/Components/EvEditor.md b/docs/source/Components/EvEditor.md index d631ac7646..d73a9ebd88 100644 --- a/docs/source/Components/EvEditor.md +++ b/docs/source/Components/EvEditor.md @@ -58,7 +58,7 @@ class CmdSetTestAttr(Command): def quit(caller): "Since we define it, we must handle messages" caller.msg("Editor exited") - key = "%s/test" % self.caller + key = f"{self.caller}/test" # launch the editor eveditor.EvEditor(self.caller, loadfunc=load, savefunc=save, quitfunc=quit, @@ -100,7 +100,7 @@ class CmdSetTestAttr(Command): key = "settestattr" def func(self): "Set up the callbacks and launch the editor" - key = "%s/test" % self.caller + key = f"{self.caller}/test" # launch the editor eveditor.EvEditor(self.caller, loadfunc=load, savefunc=save, quitfunc=quit, diff --git a/docs/source/Components/EvMenu.md b/docs/source/Components/EvMenu.md index edc73505f9..a0f6a9fbe7 100644 --- a/docs/source/Components/EvMenu.md +++ b/docs/source/Components/EvMenu.md @@ -531,10 +531,10 @@ def _set_attribute(caller, raw_string, **kwargs): def node_background(caller): text = \ - """ - {} experienced a traumatic event + f""" + {caller.key} experienced a traumatic event in their childhood. What was it? - """.format(caller.key} + """ options = ({"key": "death", "desc": "A violent death in the family", @@ -580,7 +580,7 @@ def _set_name(caller, raw_string, **kwargs): # a blank input either means OK or Abort if prev_entry: caller.key = prev_entry - caller.msg("Set name to {}.".format(prev_entry)) + caller.msg(f"Set name to {prev_entry}.") return "node_background" else: caller.msg("Aborted.") @@ -644,7 +644,7 @@ def _set_name(caller, raw_string, **kwargs): caller.ndb._menutree.charactersheet = {} caller.ndb._menutree.charactersheet['name'] = raw_string - caller.msg("You set your name to {}".format(raw_string) + caller.msg(f"You set your name to {raw_string}") return "background" def node_set_name(caller): @@ -658,7 +658,7 @@ def node_set_name(caller): def node_view_sheet(caller): - text = "Character sheet:\n {}".format(self.ndb._menutree.charactersheet) + text = f"Character sheet:\n {self.ndb._menutree.charactersheet}" options = ({"key": "Accept", "goto": "finish_chargen"}, diff --git a/docs/source/Components/Locks.md b/docs/source/Components/Locks.md index 59156c7d9e..6d1968810d 100644 --- a/docs/source/Components/Locks.md +++ b/docs/source/Components/Locks.md @@ -190,7 +190,7 @@ The above could for example be used in a lock function like this: ```python # we have `obj` and `owner_object` from before - obj.locks.add("edit: id(%i)" % owner_object.id) + obj.locks.add(f"edit: id({owner_object.id})") ``` We could check if the "edit" lock is passed with something like this: diff --git a/docs/source/Components/MonitorHandler.md b/docs/source/Components/MonitorHandler.md index 9a7a885e6a..02959ebed8 100644 --- a/docs/source/Components/MonitorHandler.md +++ b/docs/source/Components/MonitorHandler.md @@ -50,9 +50,7 @@ def _monitor_callback(fieldname="", obj=None, **kwargs): new_value = getattr(obj, fieldname) else: # an attribute new_value = obj.attributes.get(fieldname) - - obj.msg("%s.%s changed to '%s'." % \ - (obj.key, fieldname, new_value)) + obj.msg(f"{obj.key}.{fieldname} changed to '{new_value}'.") # (we could add _some_other_monitor_callback here too) diff --git a/docs/source/Components/Prototypes.md b/docs/source/Components/Prototypes.md index 1a4a348fe9..3ede8d4ede 100644 --- a/docs/source/Components/Prototypes.md +++ b/docs/source/Components/Prototypes.md @@ -176,7 +176,7 @@ def red(*args, **kwargs): """ if not args or len(args) > 1: raise ValueError("Must have one argument, the text to color red!") - return "|r{}|n".format(args[0]) + return f"|r{args[0]}|n" ``` > Note that we must make sure to validate input and raise `ValueError` if that fails. Also, it is diff --git a/docs/source/Concepts/Async-Process.md b/docs/source/Concepts/Async-Process.md index 0bb4c566d5..b2ab53011d 100644 --- a/docs/source/Concepts/Async-Process.md +++ b/docs/source/Concepts/Async-Process.md @@ -106,10 +106,10 @@ An example of making an asynchronous call from inside a [Command](../Components/ return final_value def at_return_function(r): - self.caller.msg("The final value is %s" % r) + self.caller.msg(f"The final value is {r}") def at_err_function(e): - self.caller.msg("There was an error: %s" % e) + self.caller.msg(f"There was an error: {e}") # do the async call, setting all callbacks utils.run_async(long_running_function, at_return=at_return_function, diff --git a/docs/source/Concepts/Custom-Protocols.md b/docs/source/Concepts/Custom-Protocols.md index 5cbcc2c665..ce1e2567db 100644 --- a/docs/source/Concepts/Custom-Protocols.md +++ b/docs/source/Concepts/Custom-Protocols.md @@ -79,7 +79,7 @@ This is how it looks: if not MYPROC_ENABLED: return # output to list this with the other services at startup - print(" myproc: %s" % MY_PORT) + print(f" myproc: {MY_PORT}") # some setup (simple example) factory = MyOwnFactory() diff --git a/docs/source/Concepts/Messagepath.md b/docs/source/Concepts/Messagepath.md index 1cea6024d6..fa14c7d793 100644 --- a/docs/source/Concepts/Messagepath.md +++ b/docs/source/Concepts/Messagepath.md @@ -145,7 +145,7 @@ Here are some examples ```python msg("Hello!") # using the 'text' outputfunc - msg(prompt="HP:%i, SP: %i, MP: %i" % (HP, SP, MP)) + msg(prompt=f"HP: {HP}, SP: {SP}, MP: {MP}") msg(mycommand=((1,2,3,4), {"foo": "bar"}) ``` diff --git a/docs/source/Contribs/A-voice-operated-elevator-using-events.md b/docs/source/Contribs/A-voice-operated-elevator-using-events.md index de5590d252..34c16af188 100644 --- a/docs/source/Contribs/A-voice-operated-elevator-using-events.md +++ b/docs/source/Contribs/A-voice-operated-elevator-using-events.md @@ -140,7 +140,7 @@ This is important, in order to know what variables we can use in our callback ou write a single line to be sure our callback is called when we expect it to: ```python -character.msg("You just said {}.".format(message)) +character.msg(f"You just said {message}.") ``` You can paste this line in-game, then type the `:wq` command to exit the editor and save your diff --git a/docs/source/Contribs/Building-menus.md b/docs/source/Contribs/Building-menus.md index 474654e31b..b98f9241a4 100644 --- a/docs/source/Contribs/Building-menus.md +++ b/docs/source/Contribs/Building-menus.md @@ -73,8 +73,8 @@ class EditCmd(Command): if obj.typename == "Room": Menu = RoomBuildingMenu else: - self.msg("|rThe object {} cannot be -edited.|n".format(obj.get_display_name(self.caller))) + obj_name = obj.get_display_name(self.caller) + self.msg(f"|rThe object {obj_name} cannot be edited.|n") return menu = Menu(self.caller, obj) @@ -475,8 +475,7 @@ Excessive spaces will be removed from the left for each line automatically. We information between braces... sometimes using double braces. What might be a bit odd: - `{back}` is a direct format argument we'll use (see the `.format` specifiers). -- `{{obj...}} refers to the object being edited. We use two braces, because `.format` will remove -them. +- `{{obj...}}` refers to the object being edited. We use two braces, because `.format` will remove them. In `glance`, we also use `{obj.key}` to indicate we want to show the room's key. @@ -549,7 +548,7 @@ def glance_exits(room): if room.exits: glance = "" for exit in room.exits: - glance += "\n |y{exit}|n".format(exit=exit.key) + glance += f"\n |y{exit.key}|n" return glance @@ -648,7 +647,7 @@ def glance_exits(room): if room.exits: glance = "" for exit in room.exits: - glance += "\n |y{exit}|n".format(exit=exit.key) + glance += f"\n |y{exit.key}|n" return glance @@ -662,12 +661,13 @@ def text_exits(caller, room): text += "\n\nExisting exits:" if room.exits: for exit in room.exits: - text += "\n |y@e {exit}|n".format(exit=exit.key) + text += f"\n |y@e {exit.key}|n" if exit.aliases.all(): text += " (|y{aliases}|n)".format(aliases="|n, |y".join( - alias for alias in exit.aliases.all())) + alias for alias in exit.aliases.all() + )) if exit.destination: - text += " toward {destination}".format(destination=exit.get_display_name(caller)) + text += f" toward {exit.get_display_name(caller)}" else: text += "\n\n |gNo exit has yet been defined.|n" @@ -856,21 +856,19 @@ class RoomBuildingMenu(BuildingMenu): Current title: |c{{obj.key}}|n """.format(back="|n or |y".join(self.keys_go_back))) self.add_choice_edit("description", "d") - self.add_choice("exits", "e", glance=glance_exits, text=text_exits, -on_nomatch=nomatch_exits) + self.add_choice("exits", "e", glance=glance_exits, text=text_exits, on_nomatch=nomatch_exits) # Exit sub-menu self.add_choice("exit", "e.*", text=text_single_exit, on_nomatch=nomatch_single_exit) - # Menu functions def glance_exits(room): """Show the room exits.""" if room.exits: glance = "" for exit in room.exits: - glance += "\n |y{exit}|n".format(exit=exit.key) + glance += f"\n |y{exit.key}|n" return glance @@ -884,12 +882,13 @@ def text_exits(caller, room): text += "\n\nExisting exits:" if room.exits: for exit in room.exits: - text += "\n |y@e {exit}|n".format(exit=exit.key) + text += f"\n |y@e {exit.key}|n" if exit.aliases.all(): text += " (|y{aliases}|n)".format(aliases="|n, |y".join( - alias for alias in exit.aliases.all())) + alias for alias in exit.aliases.all() + )) if exit.destination: - text += " toward {destination}".format(destination=exit.get_display_name(caller)) + text += f" toward {exit.get_display_name(caller)}" else: text += "\n\n |gNo exit has yet been defined.|n" @@ -905,7 +904,7 @@ def nomatch_exits(menu, caller, room, string): return # Open a sub-menu, using nested keys - caller.msg("Editing: {}".format(exit.key)) + caller.msg(f"Editing: {exit.key}") menu.move(exit) return False @@ -916,13 +915,13 @@ def text_single_exit(menu, caller): if exit is None: return "" - return """ - Exit {exit}: + return f""" + Exit {exit.key}: Enter the exit key to change it, or |y@|n to go back. New exit key: - """.format(exit=exit.key) + """ def nomatch_single_exit(menu, caller, room, string): """The user entered something in the exit sub-menu. Replace the exit key.""" @@ -1012,7 +1011,7 @@ def glance_exits(room): if room.exits: glance = "" for exit in room.exits: - glance += "\n |y{exit}|n".format(exit=exit.key) + glance += f"\n |y{exit.key}|n" return glance @@ -1026,12 +1025,13 @@ def text_exits(caller, room): text += "\n\nExisting exits:" if room.exits: for exit in room.exits: - text += "\n |y@e {exit}|n".format(exit=exit.key) + text += f"\n |y@e {exit.key}|n" if exit.aliases.all(): text += " (|y{aliases}|n)".format(aliases="|n, |y".join( - alias for alias in exit.aliases.all())) + alias for alias in exit.aliases.all() + )) if exit.destination: - text += " toward {destination}".format(destination=exit.get_display_name(caller)) + text += f" toward {exit.get_display_name(caller)}" else: text += "\n\n |gNo exit has yet been defined.|n" @@ -1047,7 +1047,7 @@ def nomatch_exits(menu, caller, room, string): return # Open a sub-menu, using nested keys - caller.msg("Editing: {}".format(exit.key)) + caller.msg(f"Editing: {exit.key}") menu.open_submenu("commands.building.ExitBuildingMenu", exit, parent_keys=["e"]) return False diff --git a/docs/source/Contribs/Dynamic-In-Game-Map.md b/docs/source/Contribs/Dynamic-In-Game-Map.md index 189fa892bb..5ec9d43407 100644 --- a/docs/source/Contribs/Dynamic-In-Game-Map.md +++ b/docs/source/Contribs/Dynamic-In-Game-Map.md @@ -346,7 +346,7 @@ class Room(DefaultRoom): def return_appearance(self, looker): # [...] - string = "%s\n" % Map(looker).show_map() + string = f"{Map(looker).show_map()}\n" # Add all the normal stuff like room description, # contents, exits etc. string += "\n" + super().return_appearance(looker) diff --git a/docs/source/Howto/Building-a-mech-tutorial.md b/docs/source/Howto/Building-a-mech-tutorial.md index 675cf361a0..fe59859888 100644 --- a/docs/source/Howto/Building-a-mech-tutorial.md +++ b/docs/source/Howto/Building-a-mech-tutorial.md @@ -99,8 +99,9 @@ class CmdShoot(Command): # we have an argument, search for target target = caller.search(self.args.strip()) if target: - message = "BOOM! The mech fires its gun at %s" % target.key - location.msg_contents(message) + location.msg_contents( + f"BOOM! The mech fires its gun at {target.key}" + ) class CmdLaunch(Command): # make your own 'launch'-command here as an exercise! diff --git a/docs/source/Howto/Coding-FAQ.md b/docs/source/Howto/Coding-FAQ.md index 89f809a2e0..aa7800e458 100644 --- a/docs/source/Howto/Coding-FAQ.md +++ b/docs/source/Howto/Coding-FAQ.md @@ -78,19 +78,18 @@ channel send. Edit `mygame/typeclasses/channels.py` (and then `@reload`): ```python # define our custom color names -CHANNEL_COLORS = {'public': '|015Public|n', - 'newbie': '|550N|n|551e|n|552w|n|553b|n|554i|n|555e|n', - 'staff': '|010S|n|020t|n|030a|n|040f|n|050f|n'} +CHANNEL_COLORS = {"public": "|015Public|n", + "newbie": "|550N|n|551e|n|552w|n|553b|n|554i|n|555e|n", + "staff": "|010S|n|020t|n|030a|n|040f|n|050f|n"} # Add to the Channel class # ... def channel_prefix(self, msg, emit=False): - prefix_string = "" if self.key in COLORS: - prefix_string = "[%s] " % CHANNEL_COLORS.get(self.key.lower()) + p_str = CHANNEL_COLORS.get(self.key.lower()) else: - prefix_string = "[%s] " % self.key.capitalize() - return prefix_string + p_str = self.key.capitalize() + return f"[{p_str}] " ``` Additional hint: To make colors easier to change from one place you could instead put the `CHANNEL_COLORS` dict in your settings file and import it as `from django.conf.settings import diff --git a/docs/source/Howto/Command-Duration.md b/docs/source/Howto/Command-Duration.md index fec936f920..c1bedcb4dc 100644 --- a/docs/source/Howto/Command-Duration.md +++ b/docs/source/Howto/Command-Duration.md @@ -82,16 +82,16 @@ class CmdEcho(default_cmds.MuxCommand): """ This is called at the initial shout. """ - self.caller.msg("You shout '%s' and wait for an echo ..." % self.args) + self.caller.msg(f"You shout '{self.args}' and wait for an echo ...") # this waits non-blocking for 10 seconds, then calls self.echo utils.delay(10, self.echo) # call echo after 10 seconds def echo(self): "Called after 10 seconds." shout = self.args - string = "You hear an echo: %s ... %s ... %s" - string = string % (shout.upper(), shout.capitalize(), shout.lower()) - self.caller.msg(string) + self.caller.msg( + f"You hear an echo: {shout.upper()} ... {shout.capitalize()} ... {shout.lower()}" + ) ``` Import this new echo command into the default command set and reload the server. You will find that @@ -146,7 +146,7 @@ class CmdEcho(default_cmds.MuxCommand): def func(self): "This sets off a chain of delayed calls" - self.caller.msg("You shout '%s', waiting for an echo ..." % self.args) + self.caller.msg(f"You shout '{self.args}', waiting for an echo ...") # wait 2 seconds before calling self.echo1 utils.delay(2, self.echo1) @@ -154,19 +154,19 @@ class CmdEcho(default_cmds.MuxCommand): # callback chain, started above def echo1(self): "First echo" - self.caller.msg("... %s" % self.args.upper()) + self.caller.msg(f"... {self.args.upper()}") # wait 2 seconds for the next one utils.delay(2, self.echo2) def echo2(self): "Second echo" - self.caller.msg("... %s" % self.args.capitalize()) + self.caller.msg(f"... {self.args.capitalize()}") # wait another 2 seconds utils.delay(2, callback=self.echo3) def echo3(self): "Last echo" - self.caller.msg("... %s ..." % self.args.lower()) + self.caller.msg(f"... {self.args.lower()} ...") ``` The above version will have the echoes arrive one after another, each separated by a two second @@ -364,9 +364,9 @@ from evennia import default_cmds, utils def echo(caller, args): "Called after 10 seconds." shout = args - string = "You hear an echo: %s ... %s ... %s" - string = string % (shout.upper(), shout.capitalize(), shout.lower()) - caller.msg(string) + caller.msg( + f"You hear an echo: {shout.upper()} ... {shout.capitalize()} ... {shout.lower()}" + ) class CmdEcho(default_cmds.MuxCommand): """ @@ -384,7 +384,7 @@ class CmdEcho(default_cmds.MuxCommand): """ This is called at the initial shout. """ - self.caller.msg("You shout '%s' and wait for an echo ..." % self.args) + self.caller.msg(f"You shout '{self.args}' and wait for an echo ...") # this waits non-blocking for 10 seconds, then calls echo(self.caller, self.args) utils.delay(10, echo, self.caller, self.args, persistent=True) # changes! diff --git a/docs/source/Howto/Command-Prompt.md b/docs/source/Howto/Command-Prompt.md index f3113fb23a..3a7e1dd21b 100644 --- a/docs/source/Howto/Command-Prompt.md +++ b/docs/source/Howto/Command-Prompt.md @@ -59,10 +59,8 @@ Here is a simple example of the prompt sent/updated from a command class: self.caller.msg("Not a valid target!") return - text = "You diagnose %s as having " \ - "%i health, %i mana and %i stamina." \ - % (hp, mp, sp) - prompt = "%i HP, %i MP, %i SP" % (hp, mp, sp) + text = f"You diagnose {target} as having {hp} health, {mp} mana and {sp} stamina." + prompt = f"{hp} HP, {mp} MP, {sp} SP" self.caller.msg(text, prompt=prompt) ``` ## A prompt sent with every command @@ -86,9 +84,7 @@ class MuxCommand(default_cmds.MuxCommand): def at_post_cmd(self): "called after self.func()." caller = self.caller - prompt = "%i HP, %i MP, %i SP" % (caller.db.hp, - caller.db.mp, - caller.db.sp) + prompt = f"{caller.db.hp} HP, {caller.db.mp} MP, {caller.db.sp} SP" caller.msg(prompt=prompt) ``` diff --git a/docs/source/Howto/Default-Exit-Errors.md b/docs/source/Howto/Default-Exit-Errors.md index d4032a47eb..85310894ec 100644 --- a/docs/source/Howto/Default-Exit-Errors.md +++ b/docs/source/Howto/Default-Exit-Errors.md @@ -42,7 +42,7 @@ class CmdExitError(default_cmds.MuxCommand): auto_help = False def func(self): "returns the error" - self.caller.msg("You cannot move %s." % self.key) + self.caller.msg(f"You cannot move {self.key}.") class CmdExitErrorNorth(CmdExitError): key = "north" diff --git a/docs/source/Howto/Evennia-for-roleplaying-sessions.md b/docs/source/Howto/Evennia-for-roleplaying-sessions.md index 9c8ce8690c..1d4cf22ac3 100644 --- a/docs/source/Howto/Evennia-for-roleplaying-sessions.md +++ b/docs/source/Howto/Evennia-for-roleplaying-sessions.md @@ -127,15 +127,14 @@ class Character(DefaultCharacter): if selfaccount and selfaccount.db.is_gm: # A GM. Show name as name(GM) - name = "%s(GM)" % name + name = f"{name}(GM)" if lookaccount and \ (lookaccount.permissions.get("Developers") or lookaccount.db.is_gm): # Developers/GMs see name(#dbref) or name(GM)(#dbref) - return "%s(#%s)" % (name, self.id) - else: - return name + name = f"{name}(#{self.id})" + return name ``` Above, we change how the Character's name is displayed: If the account controlling this Character is @@ -192,10 +191,10 @@ class CmdMakeGM(default_cmds.MuxCommand): accountlist = evennia.search_account(self.args) # returns a list if not accountlist: - caller.msg("Could not find account '%s'" % self.args) + caller.msg(f"Could not find account '{self.args}'") return elif len(accountlist) > 1: - caller.msg("Multiple matches for '%s': %s" % (self.args, accountlist)) + caller.msg(f"Multiple matches for '{self.args}': {accountlist}") return else: account = accountlist[0] @@ -203,20 +202,20 @@ class CmdMakeGM(default_cmds.MuxCommand): if self.cmdstring == "gm": # turn someone into a GM if account.permissions.get("Admins"): - caller.msg("Account %s is already a GM." % account) + caller.msg(f"Account {account} is already a GM.") else: account.permissions.add("Admins") - caller.msg("Account %s is now a GM." % account) - account.msg("You are now a GM (changed by %s)." % caller) + caller.msg(f"Account {account} is now a GM.") + account.msg(f"You are now a GM (changed by {caller}).") account.character.db.is_gm = True else: # @ungm was entered - revoke GM status from someone if not account.permissions.get("Admins"): - caller.msg("Account %s is not a GM." % account) + caller.msg(f"Account {account} is not a GM.") else: account.permissions.remove("Admins") - caller.msg("Account %s is no longer a GM." % account) - account.msg("You are no longer a GM (changed by %s)." % caller) + caller.msg(f"Account {account} is no longer a GM.") + account.msg(f"You are no longer a GM (changed by {caller}).") del account.character.db.is_gm ``` @@ -511,11 +510,12 @@ ALLOWED_FIELDNAMES = ALLOWED_ATTRS + \ def _validate_fieldname(caller, fieldname): "Helper function to validate field names." if fieldname not in ALLOWED_FIELDNAMES: - err = "Allowed field names: %s" % (", ".join(ALLOWED_FIELDNAMES)) + list_of_fieldnames = ", ".join(ALLOWED_FIELDNAMES) + err = f"Allowed field names: {list_of_fieldnames}" caller.msg(err) return False if fieldname in ALLOWED_ATTRS and not value.isdigit(): - caller.msg("%s must receive a number." % fieldname) + caller.msg(f"{fieldname} must receive a number.") return False return True @@ -570,7 +570,7 @@ class CmdSheet(MuxCommand): else: caller.chardata[fieldname] = value caller.update_charsheet() - caller.msg("%s was set to %s." % (fieldname, value)) + caller.msg(f"{fieldname} was set to {value}.") ``` @@ -641,13 +641,13 @@ class CmdGMsheet(MuxCommand): caller.msg("The character sheet is already locked.") else: character.db.sheet_locked = True - caller.msg("%s can no longer edit their character sheet." % character.key) + caller.msg(f"{character.key} can no longer edit their character sheet.") elif "unlock" in self.switches: if not character.db.sheet_locked: caller.msg("The character sheet is already unlocked.") else: character.db.sheet_locked = False - caller.msg("%s can now edit their character sheet." % character.key) + caller.msg(f"{character.key} can now edit their character sheet.") if fieldname: if fieldname == "name": @@ -655,7 +655,7 @@ class CmdGMsheet(MuxCommand): else: character.db.chardata[fieldname] = value character.update_charsheet() - caller.msg("You set %s's %s to %s." % (character.key, fieldname, value) + caller.msg(f"You set {character.key}'s {fieldname} to {value}.") else: # just display caller.msg(character.db.charsheet) diff --git a/docs/source/Howto/Gametime-Tutorial.md b/docs/source/Howto/Gametime-Tutorial.md index 8c1762c6a4..670a5de186 100644 --- a/docs/source/Howto/Gametime-Tutorial.md +++ b/docs/source/Howto/Gametime-Tutorial.md @@ -252,11 +252,10 @@ class CmdTime(Command): def func(self): """Execute the time command.""" # Get the absolute game time - year, month, day, hour, min, sec = custom_gametime.custom_gametime(absolute=True) - string = "We are in year {year}, day {day}, month {month}." - string += "\nIt's {hour:02}:{min:02}:{sec:02}." - self.msg(string.format(year=year, month=month, day=day, - hour=hour, min=min, sec=sec)) + year, month, day, hour, mins, secs = custom_gametime.custom_gametime(absolute=True) + time_string = f"We are in year {year}, day {day}, month {month}." + time_string += f"\nIt's {hour:02}:{mins:02}:{secs:02}." + self.msg(time_string) ``` Don't forget to add it in your CharacterCmdSet to see this command: diff --git a/docs/source/Howto/Mass-and-weight-for-objects.md b/docs/source/Howto/Mass-and-weight-for-objects.md index b1eb2b8554..fc4b028962 100644 --- a/docs/source/Howto/Mass-and-weight-for-objects.md +++ b/docs/source/Howto/Mass-and-weight-for-objects.md @@ -87,10 +87,12 @@ class CmdInventory(MuxCommand): table.border = False for item in items: second = item.get_mass() \ - if 'weight' in self.switches else item.db.desc - table.add_row(["%s" % item.get_display_name(self.caller.sessions), - second and second or ""]) - string = "|wYou are carrying:\n%s" % table + if "weight" in self.switches else item.db.desc + table.add_row([ + str(item.get_display_name(self.caller.sessions)), + second and second or "", + ]) + string = f"|wYou are carrying:\n{table}" self.caller.msg(string) ``` \ No newline at end of file diff --git a/docs/source/Howto/NPC-shop-Tutorial.md b/docs/source/Howto/NPC-shop-Tutorial.md index f06ab98862..e30c6a4573 100644 --- a/docs/source/Howto/NPC-shop-Tutorial.md +++ b/docs/source/Howto/NPC-shop-Tutorial.md @@ -86,18 +86,17 @@ def menunode_shopfront(caller): # door! Let's remove that from our for sale list. wares = [ware for ware in wares if ware.key.lower() != "door"] - text = "*** Welcome to %s! ***\n" % shopname + text = f"*** Welcome to {shopname}! ***\n" if wares: - text += " Things for sale (choose 1-%i to inspect);" \ - " quit to exit:" % len(wares) + text += f" Things for sale (choose 1-{len(wares)} to inspect); quit to exit:" else: text += " There is nothing for sale; quit to exit." options = [] for ware in wares: # add an option for every ware in store - options.append({"desc": "%s (%s gold)" % - (ware.key, ware.db.gold_value or 1), + gold_val = ware.db.gold_value or 1 + options.append({"desc": f"{ware.key} ({gold_val} gold)", "goto": "menunode_inspect_and_buy"}) return text, options ``` @@ -124,26 +123,27 @@ def menunode_inspect_and_buy(caller, raw_string): ware = wares[iware] value = ware.db.gold_value or 1 wealth = caller.db.gold or 0 - text = "You inspect %s:\n\n%s" % (ware.key, ware.db.desc) + text = f"You inspect {ware.key}:\n\n{ware.db.desc}" def buy_ware_result(caller): "This will be executed first when choosing to buy." if wealth >= value: - rtext = "You pay %i gold and purchase %s!" % \ - (value, ware.key) + rtext = f"You pay {value} gold and purchase {ware.key}!" caller.db.gold -= value ware.move_to(caller, quiet=True) else: - rtext = "You cannot afford %i gold for %s!" % \ - (value, ware.key) + rtext = f"You cannot afford {value} gold for {ware.key}!" caller.msg(rtext) - options = ({"desc": "Buy %s for %s gold" % \ - (ware.key, ware.db.gold_value or 1), - "goto": "menunode_shopfront", - "exec": buy_ware_result}, - {"desc": "Look for something else", - "goto": "menunode_shopfront"}) + gold_val = ware.db.gold_value or 1 + options = ({ + "desc": f"Buy {ware.key} for {gold_val} gold", + "goto": "menunode_shopfront", + "exec": buy_ware_result, + }, { + "desc": "Look for something else", + "goto": "menunode_shopfront", + }) return text, options ``` @@ -267,7 +267,7 @@ class CmdBuildShop(Command): key=shopname, location=None) storeroom = create_object(DefaultRoom, - key="%s-storage" % shopname, + key=f"{shopname}-storage", location=None) shop.db.storeroom = storeroom # create a door between the two @@ -281,15 +281,15 @@ class CmdBuildShop(Command): location=storeroom, destination=shop) # make a key for accessing the store room - storeroom_key_name = "%s-storekey" % shopname + storeroom_key_name = f"{shopname}-storekey" storeroom_key = create_object(DefaultObject, key=storeroom_key_name, location=shop) # only allow chars with this key to enter the store room - shop_exit.locks.add("traverse:holds(%s)" % storeroom_key_name) + shop_exit.locks.add(f"traverse:holds({storeroom_key_name})") # inform the builder about progress - self.caller.msg("The shop %s was created!" % shop) + self.caller.msg(f"The shop {shop} was created!") ``` Our typeclass is simple and so is our `buildshop` command. The command (which is for Builders only) diff --git a/docs/source/Howto/Starting/Part3/Implementing-a-game-rule-system.md b/docs/source/Howto/Starting/Part3/Implementing-a-game-rule-system.md index 80749cc971..4b8e50844f 100644 --- a/docs/source/Howto/Starting/Part3/Implementing-a-game-rule-system.md +++ b/docs/source/Howto/Starting/Part3/Implementing-a-game-rule-system.md @@ -172,7 +172,7 @@ def add_XP(character, amount): character.db.level += 1 character.db.STR += 1 character.db.combat += 2 - character.msg("You are now level %i!" % character.db.level) + character.msg(f"You are now level {character.db.level}!") def skill_combat(*args): """ @@ -182,24 +182,24 @@ def skill_combat(*args): """ char1, char2 = args roll1, roll2 = roll_hit(), roll_hit() - failtext = "You are hit by %s for %i damage!" - wintext = "You hit %s for %i damage!" + failtext_template = "You are hit by {attacker} for {dmg} damage!" + wintext_template = "You hit {target} for {dmg} damage!" xp_gain = randint(1, 3) if char1.db.combat >= roll1 > roll2: # char 1 hits dmg = roll_dmg() + char1.db.STR - char1.msg(wintext % (char2, dmg)) + char1.msg(wintext_template.format(target=char2, dmg=dmg)) add_XP(char1, xp_gain) - char2.msg(failtext % (char1, dmg)) + char2.msg(failtext_template.format(attacker=char1, dmg=dmg)) char2.db.HP -= dmg check_defeat(char2) elif char2.db.combat >= roll2 > roll1: # char 2 hits dmg = roll_dmg() + char2.db.STR - char1.msg(failtext % (char2, dmg)) + char1.msg(failtext_template.format(attacker=char2, dmg=dmg)) char1.db.HP -= dmg check_defeat(char1) - char2.msg(wintext % (char1, dmg)) + char2.msg(wintext_template.format(target=char1, dmg=dmg)) add_XP(char2, xp_gain) else: # a draw @@ -217,7 +217,7 @@ def roll_challenge(character1, character2, skillname): if skillname in SKILLS: SKILLS[skillname](character1, character2) else: - raise RunTimeError("Skillname %s not found." % skillname) + raise RunTimeError(f"Skillname {skillname} not found.") ``` These few functions implement the entirety of our simple rule system. We have a function to check diff --git a/docs/source/Howto/Starting/Part3/Turn-based-Combat-System.md b/docs/source/Howto/Starting/Part3/Turn-based-Combat-System.md index 8600667889..1b8900cef1 100644 --- a/docs/source/Howto/Starting/Part3/Turn-based-Combat-System.md +++ b/docs/source/Howto/Starting/Part3/Turn-based-Combat-System.md @@ -113,7 +113,7 @@ class CombatHandler(DefaultScript): def at_script_creation(self): "Called when script is first created" - self.key = "combat_handler_%i" % random.randint(1, 1000) + self.key = f"combat_handler_{random.randint(1, 1000)}" self.desc = "handles combat" self.interval = 60 * 2 # two minute timeout self.start_delay = True @@ -400,57 +400,58 @@ def resolve_combat(combat_handler, actiondict): taction, tchar, ttarget = actiondict[target.id][isub] if action == "hit": if taction == "parry" and ttarget == char: - msg = "%s tries to hit %s, but %s parries the attack!" - messages.append(msg % (char, tchar, tchar)) + messages.append( + f"{char} tries to hit {tchar}, but {tchar} parries the attack!" + ) elif taction == "defend" and random.random() < 0.5: - msg = "%s defends against the attack by %s." - messages.append(msg % (tchar, char)) + messages.append( + f"{tchar} defends against the attack by {char}." + ) elif taction == "flee": - msg = "%s stops %s from disengaging, with a hit!" flee[tchar] = -2 - messages.append(msg % (char, tchar)) + messages.append( + f"{char} stops {tchar} from disengaging, with a hit!" + ) else: - msg = "%s hits %s, bypassing their %s!" - messages.append(msg % (char, tchar, taction)) + messages.append( + f"{char} hits {tchar}, bypassing their {taction}!" + ) elif action == "parry": if taction == "hit": - msg = "%s parries the attack by %s." - messages.append(msg % (char, tchar)) + messages.append(f"{char} parries the attack by {tchar}.") elif taction == "feint": - msg = "%s tries to parry, but %s feints and hits!" - messages.append(msg % (char, tchar)) + messages.append( + f"{char} tries to parry, but {tchar} feints and hits!" + ) else: - msg = "%s parries to no avail." - messages.append(msg % char) + messages.append(f"{char} parries to no avail.") elif action == "feint": if taction == "parry": - msg = "%s feints past %s's parry, landing a hit!" - messages.append(msg % (char, tchar)) + messages.append( + f"{char} feints past {tchar}'s parry, landing a hit!" + ) elif taction == "hit": - msg = "%s feints but is defeated by %s hit!" - messages.append(msg % (char, tchar)) + messages.append(f"{char} feints but is defeated by {tchar}'s hit!") else: - msg = "%s feints to no avail." - messages.append(msg % char) + messages.append(f"{char} feints to no avail.") elif action == "defend": - msg = "%s defends." - messages.append(msg % char) + messages.append(f"{char} defends.") elif action == "flee": if char in flee: flee[char] += 1 else: flee[char] = 1 - msg = "%s tries to disengage (two subsequent turns needed)" - messages.append(msg % char) + messages.append( + f"{char} tries to disengage (two subsequent turns needed)" + ) # echo results of each subturn combat_handler.msg_all("\n".join(messages)) # at the end of both sub-turns, test if anyone fled - msg = "%s withdraws from combat." for (char, fleevalue) in flee.items(): if fleevalue == 2: - combat_handler.msg_all(msg % char) + combat_handler.msg_all(f"{char} withdraws from combat.") combat_handler.remove_character(char) ``` @@ -495,14 +496,14 @@ class CmdAttack(Command): if target.ndb.combat_handler: # target is already in combat - join it target.ndb.combat_handler.add_character(self.caller) - target.ndb.combat_handler.msg_all("%s joins combat!" % self.caller) + target.ndb.combat_handler.msg_all(f"{self.caller} joins combat!") else: # create a new combat handler chandler = create_script("combat_handler.CombatHandler") chandler.add_character(self.caller) chandler.add_character(target) - self.caller.msg("You attack %s! You are in combat." % target) - target.msg("%s attacks you! You are in combat." % self.caller) + self.caller.msg(f"You attack {target}! You are in combat.") + target.msg(f"{self.caller} attacks you! You are in combat.") ``` The `attack` command will not go into the combat cmdset but rather into the default cmdset. See e.g. diff --git a/docs/source/Howto/Starting/Part3/Tutorial-for-basic-MUSH-like-game.md b/docs/source/Howto/Starting/Part3/Tutorial-for-basic-MUSH-like-game.md index 940ddbd8c3..20991fc920 100644 --- a/docs/source/Howto/Starting/Part3/Tutorial-for-basic-MUSH-like-game.md +++ b/docs/source/Howto/Starting/Part3/Tutorial-for-basic-MUSH-like-game.md @@ -150,7 +150,7 @@ class CmdSetPower(Command): return # at this point the argument is tested as valid. Let's set it. self.caller.db.power = power - self.caller.msg("Your Power was set to %i." % power) + self.caller.msg(f"Your Power was set to {power}.") ``` This is a pretty straightforward command. We do some error checking, then set the power on ourself. We use a `help_category` of "mush" for all our commands, just so they are easy to find and separate @@ -295,11 +295,17 @@ class CmdAttack(Command): caller.db.combat_score = combat_score # announce - message = "%s +attack%s with a combat score of %s!" - caller.msg(message % ("You", "", combat_score)) - caller.location.msg_contents(message % - (caller.key, "s", combat_score), - exclude=caller) + message_template = "{attacker} +attack{s} with a combat score of {c_score}!" + caller.msg(message_template.format( + attacker="You", + s="", + c_score=combat_score, + )) + caller.location.msg_contents(message_template.format( + attacker=caller.key, + s="s", + c_score=combat_score, + ), exclude=caller) ``` What we do here is simply to generate a "combat score" using Python's inbuilt `random.randint()` @@ -359,7 +365,7 @@ class Character(DefaultCharacter): looker sees when looking at this object. """ text = super().return_appearance(looker) - cscore = " (combat score: %s)" % self.db.combat_score + cscore = f" (combat score: {self.db.combat_score})" if "\n" in text: # text is multi-line, add score after first line first_line, rest = text.split("\n", 1) @@ -435,12 +441,17 @@ class CmdCreateNPC(Command): npc = create_object("characters.Character", key=name, location=caller.location, - locks="edit:id(%i) and perm(Builders);call:false()" % caller.id) + locks=f"edit:id({caller.id}) and perm(Builders);call:false()") # announce - message = "%s created the NPC '%s'." - caller.msg(message % ("You", name)) - caller.location.msg_contents(message % (caller.key, name), - exclude=caller) + message_template = "{creator} created the NPC '{npc}'." + caller.msg(message_template.format( + creator="You", + npc=name, + )) + caller.location.msg_contents(message_template.format( + creator=caller.key, + npc=name, + ), exclude=caller) ``` Here we define a `+createnpc` (`+createNPC` works too) that is callable by everyone *not* having the `nonpcs` "[permission](../../../Components/Locks#Permissions)" (in Evennia, a "permission" can just as well be used to @@ -532,10 +543,10 @@ class CmdEditNPC(Command): return if not self.propname: # this means we just list the values - output = "Properties of %s:" % npc.key + output = f"Properties of {npc.key}:" for propname in allowed_propnames: propvalue = npc.attributes.get(propname, default="N/A") - output += "\n %s = %s" % (propname, propvalue) + output += f"\n {propname} = {propvalue}" caller.msg(output) elif self.propname not in allowed_propnames: caller.msg("You may only change %s." % @@ -619,7 +630,7 @@ class CmdNPC(Command): return # send the command order npc.execute_cmd(self.cmdname) - caller.msg("You told %s to do '%s'." % (npc.key, self.cmdname)) + caller.msg(f"You told {npc.key} to do '{self.cmdname}'.") ``` Note that if you give an erroneous command, you will not see any error message, since that error diff --git a/docs/source/Howto/Tutorial-NPCs-listening.md b/docs/source/Howto/Tutorial-NPCs-listening.md index b8fae5db7c..2cefe6d2c9 100644 --- a/docs/source/Howto/Tutorial-NPCs-listening.md +++ b/docs/source/Howto/Tutorial-NPCs-listening.md @@ -29,7 +29,7 @@ class Npc(Character): message = message.split('says, ')[1].strip(' "') # we'll make use of this in .msg() below - return "%s said: '%s'" % (from_obj, message) + return f"{from_obj} said: '{message}'" ``` When someone in the room speaks to this NPC, its `msg` method will be called. We will modify the @@ -60,7 +60,7 @@ class Npc(Character): # If there is a response if response != None: # speak ourselves, using the return - self.execute_cmd("say %s" % response) + self.execute_cmd(f"say {response}") # this is needed if anyone ever puppets this NPC - without it you would never # get any feedback from the server (not even the results of look) diff --git a/docs/source/Howto/Tutorial-Tweeting-Game-Stats.md b/docs/source/Howto/Tutorial-Tweeting-Game-Stats.md index de2eab527c..61e996095e 100644 --- a/docs/source/Howto/Tutorial-Tweeting-Game-Stats.md +++ b/docs/source/Howto/Tutorial-Tweeting-Game-Stats.md @@ -66,16 +66,16 @@ command keys = prototypes.keys() nprots = len(prototypes) - tweet = "Prototype Count: %s Random Keys: " % nprots + tweet = f"Prototype Count: {nprots} Random Keys: " - tweet += " %s" % keys[randint(0,len(keys)-1)] + tweet += f" {keys[randint(0,len(keys)-1)]}" for x in range(0,2): ##tweet 3 - tweet += ", %s" % keys[randint(0,len(keys)-1)] + tweet += f", {keys[randint(0,len(keys)-1)]}" # post the tweet try: response = api.PostUpdate(tweet) except: - logger.log_trace("Tweet Error: When attempting to tweet %s" % tweet) + logger.log_trace(f"Tweet Error: When attempting to tweet {tweet}") ``` In the `at_script_creation` method, we configure the script to fire immediately (useful for testing) diff --git a/docs/source/Howto/Tutorial-Vehicles.md b/docs/source/Howto/Tutorial-Vehicles.md index c0b8f03ddb..6dce8d8fa4 100644 --- a/docs/source/Howto/Tutorial-Vehicles.md +++ b/docs/source/Howto/Tutorial-Vehicles.md @@ -293,7 +293,7 @@ class TrainObject(DefaultObject): roomref = self.db.rooms[idx] room = search_object(roomref)[0] self.move_to(room) - self.msg_contents("The train is moving forward to %s." % (room.name, )) + self.msg_contents(f"The train is moving forward to {room.name}.") ``` We added a lot of code here. Since we changed the `at_object_creation` to add in variables we will diff --git a/docs/source/Howto/Web-Character-Generation.md b/docs/source/Howto/Web-Character-Generation.md index 1df0fb7e5c..122d20965e 100644 --- a/docs/source/Howto/Web-Character-Generation.md +++ b/docs/source/Howto/Web-Character-Generation.md @@ -246,8 +246,12 @@ def creating(request): user.db._playable_characters.append(char) # add the right locks for the character so the account can # puppet it - char.locks.add("puppet:id(%i) or pid(%i) or perm(Developers) " - "or pperm(Developers)" % (char.id, user.id)) + char.locks.add(" or ".join([ + f"puppet:id({char.id})", + f"pid({user.id})", + "perm(Developers)", + "pperm(Developers)", + ])) char.db.background = background # set the character background return HttpResponseRedirect('/chargen') else: @@ -332,8 +336,12 @@ def creating(request): user.db._playable_characters.append(char) # add the right locks for the character so the account can # puppet it - char.locks.add("puppet:id(%i) or pid(%i) or perm(Developers) " - "or pperm(Developers)" % (char.id, user.id)) + char.locks.add(" or ".join([ + f"puppet:id({char.id})", + f"pid({user.id})", + "perm(Developers)", + "pperm(Developers)", + ])) char.db.background = background # set the character background return HttpResponseRedirect('/chargen') else: diff --git a/docs/source/Setup/How-to-connect-Evennia-to-Twitter.md b/docs/source/Setup/How-to-connect-Evennia-to-Twitter.md index 0496b686f1..d08c18b267 100644 --- a/docs/source/Setup/How-to-connect-Evennia-to-Twitter.md +++ b/docs/source/Setup/How-to-connect-Evennia-to-Twitter.md @@ -76,13 +76,13 @@ class CmdTweet(Command): tlen = len(tweet) if tlen > 280: - caller.msg("Your tweet was %i chars long (max 280)." % tlen) + caller.msg(f"Your tweet was {tlen} chars long (max 280).") return # post the tweet TWITTER_API.PostUpdate(tweet) - caller.msg("You tweeted:\n%s" % tweet) + caller.msg(f"You tweeted:\n{tweet}") ``` Be sure to substitute your own actual API/Access keys and secrets in the appropriate places.