mirror of
https://github.com/evennia/evennia.git
synced 2026-03-16 21:06:30 +01:00
Ran formatting on code
This commit is contained in:
parent
83154de19e
commit
353e4c0aa7
20 changed files with 296 additions and 327 deletions
|
|
@ -748,7 +748,9 @@ def cmdhandler(
|
|||
)
|
||||
if suggestions:
|
||||
sysarg += _(" Maybe you meant {command}?").format(
|
||||
command=utils.list_to_string(suggestions, endsep=_("or"), addquote=True)
|
||||
command=utils.list_to_string(
|
||||
suggestions, endsep=_("or"), addquote=True
|
||||
)
|
||||
)
|
||||
else:
|
||||
sysarg += _(' Type "help" for help.')
|
||||
|
|
|
|||
|
|
@ -668,7 +668,9 @@ class CmdOption(COMMAND_DEFAULT_CLASS):
|
|||
self.msg(f"Option |w{new_name}|n was kept as '|w{old_val}|n'.")
|
||||
else:
|
||||
flags[new_name] = new_val
|
||||
self.msg(f"Option |w{new_name}|n was changed from '|w{old_val}|n' to '|w{new_val}|n'.")
|
||||
self.msg(
|
||||
f"Option |w{new_name}|n was changed from '|w{old_val}|n' to '|w{new_val}|n'."
|
||||
)
|
||||
return {new_name: new_val}
|
||||
except Exception as err:
|
||||
self.msg(f"|rCould not set option |w{new_name}|r:|n {err}")
|
||||
|
|
@ -759,7 +761,9 @@ class CmdPassword(COMMAND_DEFAULT_CLASS):
|
|||
account.set_password(newpass)
|
||||
account.save()
|
||||
self.msg("Password changed.")
|
||||
logger.log_sec(f"Password Changed: {account} (Caller: {account}, IP: {self.session.address}).")
|
||||
logger.log_sec(
|
||||
f"Password Changed: {account} (Caller: {account}, IP: {self.session.address})."
|
||||
)
|
||||
|
||||
|
||||
class CmdQuit(COMMAND_DEFAULT_CLASS):
|
||||
|
|
|
|||
|
|
@ -480,7 +480,7 @@ class CmdPerm(COMMAND_DEFAULT_CLASS):
|
|||
# we supplied an argument on the form obj = perm
|
||||
locktype = "edit" if accountmode else "control"
|
||||
if not obj.access(caller, locktype):
|
||||
accountstr = 'account' if accountmode else 'object'
|
||||
accountstr = "account" if accountmode else "object"
|
||||
caller.msg(f"You are not allowed to edit this {accountstr}'s permissions.")
|
||||
return
|
||||
|
||||
|
|
@ -521,9 +521,7 @@ class CmdPerm(COMMAND_DEFAULT_CLASS):
|
|||
return
|
||||
|
||||
if perm in permissions:
|
||||
caller_result.append(
|
||||
f"\nPermission '{perm}' is already defined on {obj.name}."
|
||||
)
|
||||
caller_result.append(f"\nPermission '{perm}' is already defined on {obj.name}.")
|
||||
else:
|
||||
obj.permissions.add(perm)
|
||||
plystring = "the Account" if accountmode else "the Object/Character"
|
||||
|
|
|
|||
|
|
@ -1392,7 +1392,7 @@ class CmdPage(COMMAND_DEFAULT_CLASS):
|
|||
|
||||
header = f"|wAccount|n |c{caller.key}|n |wpages:|n"
|
||||
if message.startswith(":"):
|
||||
message = f"{caller.key} {message.strip(':').strip()}"
|
||||
message = f"{caller.key} {message.strip(':').strip()}"
|
||||
|
||||
# create the persistent message object
|
||||
create.create_message(caller, message, receivers=targets)
|
||||
|
|
@ -1565,7 +1565,7 @@ class CmdIRC2Chan(COMMAND_DEFAULT_CLASS):
|
|||
return
|
||||
|
||||
if "disconnect" in self.switches or "remove" in self.switches or "delete" in self.switches:
|
||||
botname = f"ircbot-{self.lhs}"
|
||||
botname = f"ircbot-{self.lhs}"
|
||||
matches = AccountDB.objects.filter(db_is_bot=True, username=botname)
|
||||
dbref = utils.dbref(self.lhs)
|
||||
if not matches and dbref:
|
||||
|
|
@ -1870,7 +1870,7 @@ class CmdGrapevine2Chan(COMMAND_DEFAULT_CLASS):
|
|||
return
|
||||
|
||||
if "disconnect" in self.switches or "remove" in self.switches or "delete" in self.switches:
|
||||
botname = f"grapevinebot-{self.lhs}"
|
||||
botname = f"grapevinebot-{self.lhs}"
|
||||
matches = AccountDB.objects.filter(db_is_bot=True, db_key=botname)
|
||||
|
||||
if not matches:
|
||||
|
|
|
|||
|
|
@ -221,7 +221,8 @@ class CmdNick(COMMAND_DEFAULT_CLASS):
|
|||
_, _, old_nickstring, old_replstring = oldnick.value
|
||||
caller.nicks.remove(old_nickstring, category=nicktype)
|
||||
caller.msg(
|
||||
f"{nicktypestr} removed: '|w{old_nickstring}|n' -> |w{old_replstring}|n.")
|
||||
f"{nicktypestr} removed: '|w{old_nickstring}|n' -> |w{old_replstring}|n."
|
||||
)
|
||||
else:
|
||||
caller.msg("No matching nicks to remove.")
|
||||
return
|
||||
|
|
@ -242,9 +243,7 @@ class CmdNick(COMMAND_DEFAULT_CLASS):
|
|||
for nick in nicks:
|
||||
_, _, nick, repl = nick.value
|
||||
if nick.startswith(self.lhs):
|
||||
strings.append(
|
||||
f"{nicktype.capitalize()}-nick: '{nick}' -> '{repl}'"
|
||||
)
|
||||
strings.append(f"{nicktype.capitalize()}-nick: '{nick}' -> '{repl}'")
|
||||
if strings:
|
||||
caller.msg("\n".join(strings))
|
||||
else:
|
||||
|
|
@ -265,9 +264,7 @@ class CmdNick(COMMAND_DEFAULT_CLASS):
|
|||
for nick in nicks:
|
||||
_, _, nick, repl = nick.value
|
||||
if nick.startswith(self.lhs):
|
||||
strings.append(
|
||||
f"{nicktype.capitalize()}-nick: '{nick}' -> '{repl}'"
|
||||
)
|
||||
strings.append(f"{nicktype.capitalize()}-nick: '{nick}' -> '{repl}'")
|
||||
if strings:
|
||||
caller.msg("\n".join(strings))
|
||||
else:
|
||||
|
|
@ -288,9 +285,7 @@ class CmdNick(COMMAND_DEFAULT_CLASS):
|
|||
for nick in nicks:
|
||||
_, _, nick, repl = nick.value
|
||||
if nick.startswith(self.lhs):
|
||||
strings.append(
|
||||
f"{nicktype.capitalize()}-nick: '{nick}' -> '{repl}'"
|
||||
)
|
||||
strings.append(f"{nicktype.capitalize()}-nick: '{nick}' -> '{repl}'")
|
||||
if strings:
|
||||
caller.msg("\n".join(strings))
|
||||
else:
|
||||
|
|
@ -724,4 +719,4 @@ class CmdAccess(COMMAND_DEFAULT_CLASS):
|
|||
string += f"\nCharacter |c{caller.key}|n: {cperms}"
|
||||
if hasattr(caller, "account"):
|
||||
string += f"\nAccount |c{caller.account.key}|n: {pperms}"
|
||||
caller.msg(string)
|
||||
caller.msg(string)
|
||||
|
|
|
|||
|
|
@ -343,6 +343,7 @@ class CraftingRecipeBase:
|
|||
|
||||
class NonExistentRecipe(CraftingRecipeBase):
|
||||
"""A recipe that does not exist and never produces anything."""
|
||||
|
||||
allow_craft = True
|
||||
allow_reuse = True
|
||||
|
||||
|
|
|
|||
|
|
@ -61,21 +61,21 @@ from django.conf import settings
|
|||
from evennia import CmdSet
|
||||
from evennia.commands.default.muxcommand import MuxCommand
|
||||
|
||||
_BASIC_MAP_SIZE = settings.BASIC_MAP_SIZE if hasattr(settings, 'BASIC_MAP_SIZE') else 2
|
||||
_MAX_MAP_SIZE = settings.BASIC_MAP_SIZE if hasattr(settings, 'MAX_MAP_SIZE') else 10
|
||||
_BASIC_MAP_SIZE = settings.BASIC_MAP_SIZE if hasattr(settings, "BASIC_MAP_SIZE") else 2
|
||||
_MAX_MAP_SIZE = settings.BASIC_MAP_SIZE if hasattr(settings, "MAX_MAP_SIZE") else 10
|
||||
|
||||
# _COMPASS_DIRECTIONS specifies which way to move the pointer on the x/y axes and what characters to use to depict the exits on the map.
|
||||
_COMPASS_DIRECTIONS = {
|
||||
'north': (0, -3, ' | '),
|
||||
'south': (0, 3, ' | '),
|
||||
'east': (3, 0, '-'),
|
||||
'west': (-3, 0, '-'),
|
||||
'northeast': (3, -3, '/'),
|
||||
'northwest': (-3, -3, '\\'),
|
||||
'southeast': (3, 3, '\\'),
|
||||
'southwest': (-3, 3, '/'),
|
||||
'up': (0, 0, '^'),
|
||||
'down': (0, 0, 'v')
|
||||
"north": (0, -3, " | "),
|
||||
"south": (0, 3, " | "),
|
||||
"east": (3, 0, "-"),
|
||||
"west": (-3, 0, "-"),
|
||||
"northeast": (3, -3, "/"),
|
||||
"northwest": (-3, -3, "\\"),
|
||||
"southeast": (3, 3, "\\"),
|
||||
"southwest": (-3, 3, "/"),
|
||||
"up": (0, 0, "^"),
|
||||
"down": (0, 0, "v"),
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ class Map(object):
|
|||
"""
|
||||
self.start_time = time.time()
|
||||
self.caller = caller
|
||||
self.max_width = int(size * 2 + 1) * 5 # This must be an odd number
|
||||
self.max_width = int(size * 2 + 1) * 5 # This must be an odd number
|
||||
self.max_length = int(size * 2 + 1) * 3 # This must be an odd number
|
||||
self.has_mapped = {}
|
||||
self.curX = None
|
||||
|
|
@ -109,8 +109,8 @@ class Map(object):
|
|||
board = []
|
||||
for row in range(self.max_length):
|
||||
board.append([])
|
||||
for column in range(int(self.max_width/5)):
|
||||
board[row].extend([' ', ' ', ' '])
|
||||
for column in range(int(self.max_width / 5)):
|
||||
board[row].extend([" ", " ", " "])
|
||||
return board
|
||||
|
||||
def exit_name_as_ordinal(self, ex):
|
||||
|
|
@ -124,11 +124,13 @@ class Map(object):
|
|||
"""
|
||||
exit_name = ex.name
|
||||
if exit_name not in _COMPASS_DIRECTIONS:
|
||||
compass_aliases = [direction in ex.aliases.all() for direction in _COMPASS_DIRECTIONS.keys()]
|
||||
compass_aliases = [
|
||||
direction in ex.aliases.all() for direction in _COMPASS_DIRECTIONS.keys()
|
||||
]
|
||||
if compass_aliases[0]:
|
||||
exit_name = compass_aliases[0]
|
||||
if exit_name not in _COMPASS_DIRECTIONS:
|
||||
return ''
|
||||
return ""
|
||||
return exit_name
|
||||
|
||||
def update_pos(self, room, exit_name):
|
||||
|
|
@ -179,7 +181,7 @@ class Map(object):
|
|||
# Additionally, if the name of the exit is not ordinal but an alias of it is, use that.
|
||||
for ex in [x for x in room.exits if x.access(self.caller, "traverse")]:
|
||||
ex_name = self.exit_name_as_ordinal(ex)
|
||||
if not ex_name or ex_name in ['up', 'down']:
|
||||
if not ex_name or ex_name in ["up", "down"]:
|
||||
continue
|
||||
if self.has_drawn(ex.destination):
|
||||
continue
|
||||
|
|
@ -201,20 +203,20 @@ class Map(object):
|
|||
continue
|
||||
|
||||
ex_character = _COMPASS_DIRECTIONS[ex_name][2]
|
||||
delta_x = int(_COMPASS_DIRECTIONS[ex_name][1]/3)
|
||||
delta_y = int(_COMPASS_DIRECTIONS[ex_name][0]/3)
|
||||
delta_x = int(_COMPASS_DIRECTIONS[ex_name][1] / 3)
|
||||
delta_y = int(_COMPASS_DIRECTIONS[ex_name][0] / 3)
|
||||
|
||||
# Make modifications if the exit has BOTH up and down exits
|
||||
if ex_name == 'up':
|
||||
if 'v' in self.grid[x][y]:
|
||||
self.render_room(room, x, y, p1='^', p2='v')
|
||||
if ex_name == "up":
|
||||
if "v" in self.grid[x][y]:
|
||||
self.render_room(room, x, y, p1="^", p2="v")
|
||||
else:
|
||||
self.render_room(room, x, y, here='^')
|
||||
elif ex_name == 'down':
|
||||
if '^' in self.grid[x][y]:
|
||||
self.render_room(room, x, y, p1='^', p2='v')
|
||||
self.render_room(room, x, y, here="^")
|
||||
elif ex_name == "down":
|
||||
if "^" in self.grid[x][y]:
|
||||
self.render_room(room, x, y, p1="^", p2="v")
|
||||
else:
|
||||
self.render_room(room, x, y, here='v')
|
||||
self.render_room(room, x, y, here="v")
|
||||
else:
|
||||
self.grid[x + delta_x][y + delta_y] = ex_character
|
||||
|
||||
|
|
@ -234,7 +236,7 @@ class Map(object):
|
|||
self.has_mapped[room] = [self.curX, self.curY]
|
||||
self.render_room(room, self.curX, self.curY)
|
||||
|
||||
def render_room(self, room, x, y, p1='[', p2=']', here=None):
|
||||
def render_room(self, room, x, y, p1="[", p2="]", here=None):
|
||||
"""
|
||||
Draw a given room with ascii characters
|
||||
|
||||
|
|
@ -253,7 +255,7 @@ class Map(object):
|
|||
you[0] = f"{p1}|n"
|
||||
you[1] = f"{here if here else you[1]}"
|
||||
if room == self.caller.location:
|
||||
you[1] = '|[x|co|n' # Highlight the location you are currently in
|
||||
you[1] = "|[x|co|n" # Highlight the location you are currently in
|
||||
you[2] = f"{p2}|n"
|
||||
|
||||
self.grid[x][y] = "".join(you)
|
||||
|
|
@ -300,6 +302,7 @@ class CmdMap(MuxCommand):
|
|||
|
||||
Usage: map (optional size)
|
||||
"""
|
||||
|
||||
key = "map"
|
||||
|
||||
def func(self):
|
||||
|
|
|
|||
|
|
@ -17,19 +17,32 @@ class TestIngameMap(BaseEvenniaCommandTest):
|
|||
Expected output:
|
||||
[ ]--[ ]
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.west_room = create_object(rooms.Room, key="Room 1")
|
||||
self.east_room = create_object(rooms.Room, key="Room 2")
|
||||
create_object(exits.Exit, key="east", aliases=["e"], location=self.west_room, destination=self.east_room)
|
||||
create_object(exits.Exit, key="west", aliases=["w"], location=self.east_room, destination=self.west_room)
|
||||
create_object(
|
||||
exits.Exit,
|
||||
key="east",
|
||||
aliases=["e"],
|
||||
location=self.west_room,
|
||||
destination=self.east_room,
|
||||
)
|
||||
create_object(
|
||||
exits.Exit,
|
||||
key="west",
|
||||
aliases=["w"],
|
||||
location=self.east_room,
|
||||
destination=self.west_room,
|
||||
)
|
||||
|
||||
def test_west_room_map_room(self):
|
||||
self.char1.location = self.west_room
|
||||
map_here = ingame_map_display.Map(self.char1).show_map()
|
||||
self.assertEqual(map_here.strip(), '[|n|[x|co|n]|n--[|n ]|n')
|
||||
self.assertEqual(map_here.strip(), "[|n|[x|co|n]|n--[|n ]|n")
|
||||
|
||||
def test_east_room_map_room(self):
|
||||
self.char1.location = self.east_room
|
||||
map_here = ingame_map_display.Map(self.char1).show_map()
|
||||
self.assertEqual(map_here.strip(), '[|n ]|n--[|n|[x|co|n]|n')
|
||||
self.assertEqual(map_here.strip(), "[|n ]|n--[|n|[x|co|n]|n")
|
||||
|
|
|
|||
|
|
@ -1421,16 +1421,19 @@ class TestBuildExampleGrid(BaseEvenniaTest):
|
|||
mock_room_callbacks = mock.MagicMock()
|
||||
mock_exit_callbacks = mock.MagicMock()
|
||||
|
||||
|
||||
class TestXyzRoom(xyzroom.XYZRoom):
|
||||
def at_object_creation(self):
|
||||
mock_room_callbacks.at_object_creation()
|
||||
def at_object_creation(self):
|
||||
mock_room_callbacks.at_object_creation()
|
||||
|
||||
|
||||
class TestXyzExit(xyzroom.XYZExit):
|
||||
def at_object_creation(self):
|
||||
mock_exit_callbacks.at_object_creation()
|
||||
def at_object_creation(self):
|
||||
mock_exit_callbacks.at_object_creation()
|
||||
|
||||
|
||||
MAP_DATA = {
|
||||
"map": """
|
||||
"map": """
|
||||
|
||||
+ 0 1
|
||||
|
||||
|
|
@ -1439,35 +1442,37 @@ MAP_DATA = {
|
|||
+ 0 1
|
||||
|
||||
""",
|
||||
"zcoord": "map1",
|
||||
"prototypes": {
|
||||
("*", "*"): {
|
||||
"key": "room",
|
||||
"desc": "A room.",
|
||||
"prototype_parent": "xyz_room",
|
||||
},
|
||||
("*", "*", "*"): {
|
||||
"desc": "A passage.",
|
||||
"prototype_parent": "xyz_exit",
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"map_visual_range": 1,
|
||||
"map_mode": "scan",
|
||||
}
|
||||
"zcoord": "map1",
|
||||
"prototypes": {
|
||||
("*", "*"): {
|
||||
"key": "room",
|
||||
"desc": "A room.",
|
||||
"prototype_parent": "xyz_room",
|
||||
},
|
||||
("*", "*", "*"): {
|
||||
"desc": "A passage.",
|
||||
"prototype_parent": "xyz_exit",
|
||||
},
|
||||
},
|
||||
"options": {
|
||||
"map_visual_range": 1,
|
||||
"map_mode": "scan",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class TestCallbacks(BaseEvenniaTest):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
mock_room_callbacks.reset_mock()
|
||||
mock_exit_callbacks.reset_mock()
|
||||
|
||||
|
||||
def setup_grid(self, map_data):
|
||||
self.grid, err = xyzgrid.XYZGrid.create("testgrid")
|
||||
|
||||
def _log(msg):
|
||||
print(msg)
|
||||
print(msg)
|
||||
|
||||
self.grid.log = _log
|
||||
|
||||
self.map_data = map_data
|
||||
|
|
@ -1489,5 +1494,9 @@ class TestCallbacks(BaseEvenniaTest):
|
|||
self.grid.spawn()
|
||||
|
||||
# Two rooms and 2 exits, Each one should have gotten one `at_object_creation` callback.
|
||||
self.assertEqual(mock_room_callbacks.at_object_creation.mock_calls, [mock.call(), mock.call()])
|
||||
self.assertEqual(mock_exit_callbacks.at_object_creation.mock_calls, [mock.call(), mock.call()])
|
||||
self.assertEqual(
|
||||
mock_room_callbacks.at_object_creation.mock_calls, [mock.call(), mock.call()]
|
||||
)
|
||||
self.assertEqual(
|
||||
mock_exit_callbacks.at_object_creation.mock_calls, [mock.call(), mock.call()]
|
||||
)
|
||||
|
|
|
|||
|
|
@ -321,7 +321,9 @@ class MapNode:
|
|||
# with proper coordinates etc
|
||||
typeclass = self.prototype.get("typeclass")
|
||||
if typeclass is None:
|
||||
raise MapError(f"The prototype {self.prototype} for this node has no 'typeclass' key.", self)
|
||||
raise MapError(
|
||||
f"The prototype {self.prototype} for this node has no 'typeclass' key.", self
|
||||
)
|
||||
self.log(f" spawning room at xyz={xyz} ({typeclass})")
|
||||
Typeclass = class_from_module(typeclass)
|
||||
nodeobj, err = Typeclass.create(self.prototype.get("key", "An empty room"), xyz=xyz)
|
||||
|
|
@ -405,7 +407,10 @@ class MapNode:
|
|||
prot = maplinks[key.lower()][3].prototype
|
||||
typeclass = prot.get("typeclass")
|
||||
if typeclass is None:
|
||||
raise MapError(f"The prototype {self.prototype} for this node has no 'typeclass' key.", self)
|
||||
raise MapError(
|
||||
f"The prototype {self.prototype} for this node has no 'typeclass' key.",
|
||||
self,
|
||||
)
|
||||
self.log(f" spawning/updating exit xyz={xyz}, direction={key} ({typeclass})")
|
||||
|
||||
Typeclass = class_from_module(typeclass)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ from evennia.server.sessionhandler import SESSIONS
|
|||
import git
|
||||
import datetime
|
||||
|
||||
|
||||
class GitCommand(MuxCommand):
|
||||
"""
|
||||
The shared functionality between git/git evennia
|
||||
|
|
@ -17,31 +18,35 @@ class GitCommand(MuxCommand):
|
|||
Parse the arguments, set default arg to 'status' and check for existence of currently targeted repo
|
||||
"""
|
||||
super().parse()
|
||||
|
||||
|
||||
if self.args:
|
||||
split_args = self.args.strip().split(" ", 1)
|
||||
self.action = split_args[0]
|
||||
if len(split_args) > 1:
|
||||
self.args = ''.join(split_args[1:])
|
||||
self.args = "".join(split_args[1:])
|
||||
else:
|
||||
self.args = ''
|
||||
self.args = ""
|
||||
else:
|
||||
self.action = "status"
|
||||
self.args = ""
|
||||
|
||||
self.err_msgs = ["|rInvalid Git Repository|n:",
|
||||
|
||||
self.err_msgs = [
|
||||
"|rInvalid Git Repository|n:",
|
||||
"The {repo_type} repository is not recognized as a git directory.",
|
||||
"In order to initialize it as a git directory, you will need to access your terminal and run the following commands from within your directory:",
|
||||
" git init",
|
||||
" git remote add origin {remote_link}"]
|
||||
|
||||
" git remote add origin {remote_link}",
|
||||
]
|
||||
|
||||
try:
|
||||
self.repo = git.Repo(self.directory, search_parent_directories=True)
|
||||
except git.exc.InvalidGitRepositoryError:
|
||||
err_msg = '\n'.join(self.err_msgs).format(repo_type=self.repo_type, remote_link=self.remote_link)
|
||||
err_msg = "\n".join(self.err_msgs).format(
|
||||
repo_type=self.repo_type, remote_link=self.remote_link
|
||||
)
|
||||
self.caller.msg(err_msg)
|
||||
raise InterruptCommand
|
||||
|
||||
|
||||
self.commit = self.repo.head.commit
|
||||
|
||||
try:
|
||||
|
|
@ -56,16 +61,20 @@ class GitCommand(MuxCommand):
|
|||
"""
|
||||
short_sha = repo.git.rev_parse(hexsha, short=True)
|
||||
return short_sha
|
||||
|
||||
|
||||
def get_status(self):
|
||||
"""
|
||||
Retrieves the status of the active git repository, displaying unstaged changes/untracked files.
|
||||
"""
|
||||
time_of_commit = datetime.datetime.fromtimestamp(self.commit.committed_date)
|
||||
status_msg = '\n'.join([f"Branch: |w{self.branch}|n ({self.repo.git.rev_parse(self.commit.hexsha, short=True)}) ({time_of_commit})",
|
||||
f"By {self.commit.author.email}: {self.commit.message}"])
|
||||
status_msg = "\n".join(
|
||||
[
|
||||
f"Branch: |w{self.branch}|n ({self.repo.git.rev_parse(self.commit.hexsha, short=True)}) ({time_of_commit})",
|
||||
f"By {self.commit.author.email}: {self.commit.message}",
|
||||
]
|
||||
)
|
||||
|
||||
changedFiles = { item.a_path for item in self.repo.index.diff(None) }
|
||||
changedFiles = {item.a_path for item in self.repo.index.diff(None)}
|
||||
if changedFiles:
|
||||
status_msg += f"Unstaged/uncommitted changes:|/ |g{'|/ '.join(changedFiles)}|n|/"
|
||||
if len(self.repo.untracked_files) > 0:
|
||||
|
|
@ -77,7 +86,9 @@ class GitCommand(MuxCommand):
|
|||
Display current and available branches.
|
||||
"""
|
||||
remote_refs = self.repo.remote().refs
|
||||
branch_msg = f"Current branch: |w{self.branch}|n. Branches available: {list_to_string(remote_refs)}"
|
||||
branch_msg = (
|
||||
f"Current branch: |w{self.branch}|n. Branches available: {list_to_string(remote_refs)}"
|
||||
)
|
||||
return branch_msg
|
||||
|
||||
def checkout(self):
|
||||
|
|
@ -85,7 +96,9 @@ class GitCommand(MuxCommand):
|
|||
Check out a specific branch.
|
||||
"""
|
||||
remote_refs = self.repo.remote().refs
|
||||
to_branch = self.args.strip().removeprefix('origin/') # Slightly hacky, but git tacks on the origin/
|
||||
to_branch = self.args.strip().removeprefix(
|
||||
"origin/"
|
||||
) # Slightly hacky, but git tacks on the origin/
|
||||
|
||||
if to_branch not in remote_refs:
|
||||
self.caller.msg(f"Branch '{to_branch}' not available.")
|
||||
|
|
@ -101,7 +114,7 @@ class GitCommand(MuxCommand):
|
|||
return False
|
||||
self.msg(f"Checked out |w{to_branch}|n successfully. Server restart initiated.")
|
||||
return True
|
||||
|
||||
|
||||
def pull(self):
|
||||
"""
|
||||
Attempt to pull new code.
|
||||
|
|
@ -116,7 +129,9 @@ class GitCommand(MuxCommand):
|
|||
self.caller.msg("No new code to pull, no need to reset.\n")
|
||||
return False
|
||||
else:
|
||||
self.caller.msg(f"You have pulled new code. Server restart initiated.|/Head now at {self.repo.git.rev_parse(self.repo.head.commit.hexsha, short=True)}.|/Author: {self.repo.head.commit.author.name} ({self.repo.head.commit.author.email})|/{self.repo.head.commit.message.strip()}")
|
||||
self.caller.msg(
|
||||
f"You have pulled new code. Server restart initiated.|/Head now at {self.repo.git.rev_parse(self.repo.head.commit.hexsha, short=True)}.|/Author: {self.repo.head.commit.author.name} ({self.repo.head.commit.author.email})|/{self.repo.head.commit.message.strip()}"
|
||||
)
|
||||
return True
|
||||
|
||||
def func(self):
|
||||
|
|
@ -139,18 +154,19 @@ class GitCommand(MuxCommand):
|
|||
caller.msg("You can only git status, git branch, git checkout, or git pull.")
|
||||
return
|
||||
|
||||
|
||||
class CmdGitEvennia(GitCommand):
|
||||
"""
|
||||
Pull the latest code from the evennia core or checkout a different branch.
|
||||
|
||||
|
||||
Usage:
|
||||
git evennia status - View an overview of the evennia repository status.
|
||||
git evennia branch - View available branches in evennia.
|
||||
git evennia checkout <branch> - Checkout a different branch in evennia.
|
||||
git evennia pull - Pull the latest evennia code.
|
||||
|
||||
|
||||
For updating your local mygame repository, the same commands are available with 'git'.
|
||||
|
||||
|
||||
If there are any conflicts encountered, the command will abort. The command will reload your game after pulling new code automatically, but for some changes involving persistent scripts etc, you may need to manually restart.
|
||||
"""
|
||||
|
||||
|
|
@ -173,7 +189,7 @@ class CmdGit(GitCommand):
|
|||
git pull - Pull the latest code from your current branch.
|
||||
|
||||
For updating evennia code, the same commands are available with 'git evennia'.
|
||||
|
||||
|
||||
If there are any conflicts encountered, the command will abort. The command will reload your game after pulling new code automatically, but for changes involving persistent scripts etc, you may need to manually restart.
|
||||
"""
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import git
|
|||
import mock
|
||||
import datetime
|
||||
|
||||
|
||||
class TestGitIntegration(EvenniaTest):
|
||||
@mock.patch("git.Repo")
|
||||
@mock.patch("git.Git")
|
||||
|
|
@ -45,11 +46,15 @@ class TestGitIntegration(EvenniaTest):
|
|||
test_cmd_git.caller = self.char1
|
||||
test_cmd_git.args = "nonexistent_branch"
|
||||
self.test_cmd_git = test_cmd_git
|
||||
|
||||
|
||||
def test_git_status(self):
|
||||
time_of_commit = datetime.datetime.fromtimestamp(self.test_cmd_git.commit.committed_date)
|
||||
status_msg = '\n'.join([f"Branch: |w{self.test_cmd_git.branch}|n ({self.test_cmd_git.repo.git.rev_parse(self.test_cmd_git.commit.hexsha, short=True)}) ({time_of_commit})",
|
||||
f"By {self.test_cmd_git.commit.author.email}: {self.test_cmd_git.commit.message}"])
|
||||
status_msg = "\n".join(
|
||||
[
|
||||
f"Branch: |w{self.test_cmd_git.branch}|n ({self.test_cmd_git.repo.git.rev_parse(self.test_cmd_git.commit.hexsha, short=True)}) ({time_of_commit})",
|
||||
f"By {self.test_cmd_git.commit.author.email}: {self.test_cmd_git.commit.message}",
|
||||
]
|
||||
)
|
||||
self.assertEqual(status_msg, self.test_cmd_git.get_status())
|
||||
|
||||
def test_git_branch(self):
|
||||
|
|
@ -62,8 +67,9 @@ class TestGitIntegration(EvenniaTest):
|
|||
# Checkout no branch
|
||||
self.test_cmd_git.checkout()
|
||||
self.char1.msg.assert_called_with("Branch 'nonexistent_branch' not available.")
|
||||
|
||||
|
||||
def test_git_pull(self):
|
||||
self.test_cmd_git.pull()
|
||||
self.char1.msg.assert_called_with(f"You have pulled new code. Server restart initiated.|/Head now at {self.repo.git.rev_parse(self.repo.head.commit.hexsha, short=True)}.|/Author: {self.repo.head.commit.author.name} ({self.repo.head.commit.author.email})|/{self.repo.head.commit.message.strip()}")
|
||||
|
||||
self.char1.msg.assert_called_with(
|
||||
f"You have pulled new code. Server restart initiated.|/Head now at {self.repo.git.rev_parse(self.repo.head.commit.hexsha, short=True)}.|/Author: {self.repo.head.commit.author.name} ({self.repo.head.commit.author.email})|/{self.repo.head.commit.message.strip()}"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ from evennia.utils.utils import callables_from_module, class_from_module
|
|||
|
||||
SCRIPTDB = None
|
||||
|
||||
|
||||
class Container:
|
||||
"""
|
||||
Base container class. A container is simply a storage object whose
|
||||
|
|
@ -203,7 +204,9 @@ class GlobalScriptContainer(Container):
|
|||
self.typeclass_storage = {}
|
||||
for key, data in list(self.loaded_data.items()):
|
||||
typeclass = data.get("typeclass", settings.BASE_SCRIPT_TYPECLASS)
|
||||
self.typeclass_storage[key] = class_from_module(typeclass, fallback=settings.BASE_SCRIPT_TYPECLASS)
|
||||
self.typeclass_storage[key] = class_from_module(
|
||||
typeclass, fallback=settings.BASE_SCRIPT_TYPECLASS
|
||||
)
|
||||
|
||||
def get(self, key, default=None):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -6,5 +6,6 @@ dependencies.
|
|||
|
||||
from evennia import nonexistent_module, DefaultScript
|
||||
|
||||
|
||||
class BrokenScript(DefaultScript):
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -8,14 +8,16 @@ from evennia import DefaultScript
|
|||
|
||||
_BASE_TYPECLASS = class_from_module(settings.BASE_SCRIPT_TYPECLASS)
|
||||
|
||||
|
||||
class GoodScript(DefaultScript):
|
||||
pass
|
||||
|
||||
|
||||
class InvalidScript:
|
||||
pass
|
||||
|
||||
class TestGlobalScriptContainer(unittest.TestCase):
|
||||
|
||||
class TestGlobalScriptContainer(unittest.TestCase):
|
||||
def test_init_with_no_scripts(self):
|
||||
gsc = containers.GlobalScriptContainer()
|
||||
|
||||
|
|
@ -29,7 +31,7 @@ class TestGlobalScriptContainer(unittest.TestCase):
|
|||
|
||||
self.assertEqual(len(gsc.typeclass_storage), 0)
|
||||
|
||||
@override_settings(GLOBAL_SCRIPTS={'script_name': {}})
|
||||
@override_settings(GLOBAL_SCRIPTS={"script_name": {}})
|
||||
def test_start_with_typeclassless_script(self):
|
||||
"""No specified typeclass should fallback to base"""
|
||||
gsc = containers.GlobalScriptContainer()
|
||||
|
|
@ -37,10 +39,14 @@ class TestGlobalScriptContainer(unittest.TestCase):
|
|||
gsc.start()
|
||||
|
||||
self.assertEqual(len(gsc.typeclass_storage), 1)
|
||||
self.assertIn('script_name', gsc.typeclass_storage)
|
||||
self.assertEqual(gsc.typeclass_storage['script_name'], _BASE_TYPECLASS)
|
||||
self.assertIn("script_name", gsc.typeclass_storage)
|
||||
self.assertEqual(gsc.typeclass_storage["script_name"], _BASE_TYPECLASS)
|
||||
|
||||
@override_settings(GLOBAL_SCRIPTS={'script_name': {'typeclass': 'evennia.utils.tests.test_containers.NoScript'}})
|
||||
@override_settings(
|
||||
GLOBAL_SCRIPTS={
|
||||
"script_name": {"typeclass": "evennia.utils.tests.test_containers.NoScript"}
|
||||
}
|
||||
)
|
||||
def test_start_with_nonexistent_script(self):
|
||||
"""Missing script class should fall back to base"""
|
||||
gsc = containers.GlobalScriptContainer()
|
||||
|
|
@ -48,35 +54,53 @@ class TestGlobalScriptContainer(unittest.TestCase):
|
|||
gsc.start()
|
||||
|
||||
self.assertEqual(len(gsc.typeclass_storage), 1)
|
||||
self.assertIn('script_name', gsc.typeclass_storage)
|
||||
self.assertEqual(gsc.typeclass_storage['script_name'], _BASE_TYPECLASS)
|
||||
self.assertIn("script_name", gsc.typeclass_storage)
|
||||
self.assertEqual(gsc.typeclass_storage["script_name"], _BASE_TYPECLASS)
|
||||
|
||||
@override_settings(GLOBAL_SCRIPTS={'script_name': {'typeclass': 'evennia.utils.tests.test_containers.GoodScript'}})
|
||||
@override_settings(
|
||||
GLOBAL_SCRIPTS={
|
||||
"script_name": {"typeclass": "evennia.utils.tests.test_containers.GoodScript"}
|
||||
}
|
||||
)
|
||||
def test_start_with_valid_script(self):
|
||||
gsc = containers.GlobalScriptContainer()
|
||||
|
||||
gsc.start()
|
||||
|
||||
self.assertEqual(len(gsc.typeclass_storage), 1)
|
||||
self.assertIn('script_name', gsc.typeclass_storage)
|
||||
self.assertEqual(gsc.typeclass_storage['script_name'], GoodScript)
|
||||
self.assertIn("script_name", gsc.typeclass_storage)
|
||||
self.assertEqual(gsc.typeclass_storage["script_name"], GoodScript)
|
||||
|
||||
@override_settings(GLOBAL_SCRIPTS={'script_name': {'typeclass': 'evennia.utils.tests.test_containers.InvalidScript'}})
|
||||
@override_settings(
|
||||
GLOBAL_SCRIPTS={
|
||||
"script_name": {"typeclass": "evennia.utils.tests.test_containers.InvalidScript"}
|
||||
}
|
||||
)
|
||||
def test_start_with_invalid_script(self):
|
||||
"""Script class doesn't implement required methods methods"""
|
||||
gsc = containers.GlobalScriptContainer()
|
||||
|
||||
with self.assertRaises(AttributeError) as err:
|
||||
with self.assertRaises(AttributeError) as err:
|
||||
gsc.start()
|
||||
# check for general attribute failure on the invalid class to preserve against future code-rder changes
|
||||
self.assertTrue(str(err.exception).startswith("type object 'InvalidScript' has no attribute"), err.exception)
|
||||
self.assertTrue(
|
||||
str(err.exception).startswith("type object 'InvalidScript' has no attribute"),
|
||||
err.exception,
|
||||
)
|
||||
|
||||
@override_settings(GLOBAL_SCRIPTS={'script_name': {'typeclass': 'evennia.utils.tests.data.broken_script.BrokenScript'}})
|
||||
@override_settings(
|
||||
GLOBAL_SCRIPTS={
|
||||
"script_name": {"typeclass": "evennia.utils.tests.data.broken_script.BrokenScript"}
|
||||
}
|
||||
)
|
||||
def test_start_with_broken_script(self):
|
||||
"""Un-importable script should traceback"""
|
||||
gsc = containers.GlobalScriptContainer()
|
||||
|
||||
with self.assertRaises(Exception) as err:
|
||||
with self.assertRaises(Exception) as err:
|
||||
gsc.start()
|
||||
# exception raised by imported module
|
||||
self.assertTrue(str(err.exception).startswith("cannot import name 'nonexistent_module' from 'evennia'"), err.exception)
|
||||
self.assertTrue(
|
||||
str(err.exception).startswith("cannot import name 'nonexistent_module' from 'evennia'"),
|
||||
err.exception,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -353,12 +353,9 @@ class TestTextToHTMLparser(TestCase):
|
|||
|
||||
def test_non_url_with_www(self):
|
||||
self.assertEqual(
|
||||
self.parser.convert_urls('Awwww.this should not be highlighted'),
|
||||
'Awwww.this should not be highlighted'
|
||||
self.parser.convert_urls("Awwww.this should not be highlighted"),
|
||||
"Awwww.this should not be highlighted",
|
||||
)
|
||||
|
||||
def test_invalid_www_url(self):
|
||||
self.assertEqual(
|
||||
self.parser.convert_urls('www.t'),
|
||||
'www.t'
|
||||
)
|
||||
self.assertEqual(self.parser.convert_urls("www.t"), "www.t")
|
||||
|
|
|
|||
|
|
@ -721,10 +721,10 @@ class TestIntConversions(TestCase):
|
|||
# basic mapped numbers
|
||||
self.assertEqual(3, utils.str2int("three"))
|
||||
self.assertEqual(20, utils.str2int("twenty"))
|
||||
|
||||
|
||||
# multi-place numbers
|
||||
self.assertEqual(2345, utils.str2int("two thousand, three hundred and forty-five"))
|
||||
|
||||
|
||||
# ordinal numbers
|
||||
self.assertEqual(1, utils.str2int("1st"))
|
||||
self.assertEqual(1, utils.str2int("first"))
|
||||
|
|
@ -734,4 +734,4 @@ class TestIntConversions(TestCase):
|
|||
self.assertEqual(20, utils.str2int("twentieth"))
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
utils.str2int("not a number")
|
||||
utils.str2int("not a number")
|
||||
|
|
|
|||
|
|
@ -90,8 +90,10 @@ class TextToHTMLparser(object):
|
|||
re_url = re.compile(
|
||||
r'(?<!=")(\b(?:ftp|www|https?)\W+(?:(?!\.(?:\s|$)|&\w+;)[^"\',;$*^\\(){}<>\[\]\s])+)(\.(?:\s|$)|&\w+;|)'
|
||||
)
|
||||
re_protocol = re.compile(r'^(?:ftp|https?)://')
|
||||
re_valid_no_protocol = re.compile(r'^(?:www|ftp)\.[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b[-a-zA-Z0-9@:%_\+.~#?&//=]*')
|
||||
re_protocol = re.compile(r"^(?:ftp|https?)://")
|
||||
re_valid_no_protocol = re.compile(
|
||||
r"^(?:www|ftp)\.[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b[-a-zA-Z0-9@:%_\+.~#?&//=]*"
|
||||
)
|
||||
re_mxplink = re.compile(r"\|lc(.*?)\|lt(.*?)\|le", re.DOTALL)
|
||||
re_mxpurl = re.compile(r"\|lu(.*?)\|lt(.*?)\|le", re.DOTALL)
|
||||
|
||||
|
|
@ -151,20 +153,24 @@ class TextToHTMLparser(object):
|
|||
"""
|
||||
m = self.re_url.search(text)
|
||||
if m:
|
||||
href = m.group(1)
|
||||
label = href
|
||||
# if there is no protocol (i.e. starts with www or ftp)
|
||||
# prefix with http:// so the link isn't treated as relative
|
||||
if not self.re_protocol.match(href):
|
||||
if not self.re_valid_no_protocol.match(href):
|
||||
return text
|
||||
href = "http://" + href
|
||||
rest = m.group(2)
|
||||
# -> added target to output prevent the web browser from attempting to
|
||||
# change pages (and losing our webclient session).
|
||||
return text[:m.start()] + f'<a href="{href}" target="_blank">{label}</a>{rest}' + text[m.end():]
|
||||
href = m.group(1)
|
||||
label = href
|
||||
# if there is no protocol (i.e. starts with www or ftp)
|
||||
# prefix with http:// so the link isn't treated as relative
|
||||
if not self.re_protocol.match(href):
|
||||
if not self.re_valid_no_protocol.match(href):
|
||||
return text
|
||||
href = "http://" + href
|
||||
rest = m.group(2)
|
||||
# -> added target to output prevent the web browser from attempting to
|
||||
# change pages (and losing our webclient session).
|
||||
return (
|
||||
text[: m.start()]
|
||||
+ f'<a href="{href}" target="_blank">{label}</a>{rest}'
|
||||
+ text[m.end() :]
|
||||
)
|
||||
else:
|
||||
return text
|
||||
return text
|
||||
|
||||
def sub_mxp_links(self, match):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -59,10 +59,7 @@ PRONOUN_MAPPING = {
|
|||
"neutral": "mine",
|
||||
"plural": "ours",
|
||||
},
|
||||
"reflexive pronoun": {
|
||||
"neutral": "myself",
|
||||
"plural": "ourselves"
|
||||
}
|
||||
"reflexive pronoun": {"neutral": "myself", "plural": "ourselves"},
|
||||
},
|
||||
"2nd person": {
|
||||
"subject pronoun": {
|
||||
|
|
@ -80,26 +77,16 @@ PRONOUN_MAPPING = {
|
|||
"reflexive pronoun": {
|
||||
"neutral": "yourself",
|
||||
"plural": "yourselves",
|
||||
}
|
||||
},
|
||||
},
|
||||
"3rd person": {
|
||||
"subject pronoun": {
|
||||
"male": "he",
|
||||
"female": "she",
|
||||
"neutral": "it",
|
||||
"plural": "they"
|
||||
},
|
||||
"object pronoun": {
|
||||
"male": "him",
|
||||
"female": "her",
|
||||
"neutral": "it",
|
||||
"plural": "them"
|
||||
},
|
||||
"subject pronoun": {"male": "he", "female": "she", "neutral": "it", "plural": "they"},
|
||||
"object pronoun": {"male": "him", "female": "her", "neutral": "it", "plural": "them"},
|
||||
"possessive adjective": {
|
||||
"male": "his",
|
||||
"female": "her",
|
||||
"neutral": "its",
|
||||
"plural": "their"
|
||||
"plural": "their",
|
||||
},
|
||||
"possessive pronoun": {
|
||||
"male": "his",
|
||||
|
|
@ -113,166 +100,61 @@ PRONOUN_MAPPING = {
|
|||
"neutral": "itself",
|
||||
"plural": "themselves",
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
PRONOUN_TABLE = {
|
||||
"I": (
|
||||
"1st person",
|
||||
("neutral", "male", "female"),
|
||||
"subject pronoun"
|
||||
),
|
||||
"me": (
|
||||
"1st person",
|
||||
("neutral", "male", "female"),
|
||||
"object pronoun"
|
||||
),
|
||||
"my": (
|
||||
"1st person",
|
||||
("neutral", "male", "female"),
|
||||
"possessive adjective"
|
||||
),
|
||||
"mine": (
|
||||
"1st person",
|
||||
("neutral", "male", "female"),
|
||||
"possessive pronoun"
|
||||
),
|
||||
"myself": (
|
||||
"1st person",
|
||||
("neutral", "male", "female"),
|
||||
"reflexive pronoun"
|
||||
),
|
||||
|
||||
"we": (
|
||||
"1st person",
|
||||
"plural",
|
||||
"subject pronoun"
|
||||
),
|
||||
"us": (
|
||||
"1st person",
|
||||
"plural",
|
||||
"object pronoun"
|
||||
),
|
||||
"our": (
|
||||
"1st person",
|
||||
"plural",
|
||||
"possessive adjective"
|
||||
),
|
||||
"ours": (
|
||||
"1st person",
|
||||
"plural",
|
||||
"possessive pronoun"
|
||||
),
|
||||
"ourselves": (
|
||||
"1st person",
|
||||
"plural",
|
||||
"reflexive pronoun"
|
||||
),
|
||||
"I": ("1st person", ("neutral", "male", "female"), "subject pronoun"),
|
||||
"me": ("1st person", ("neutral", "male", "female"), "object pronoun"),
|
||||
"my": ("1st person", ("neutral", "male", "female"), "possessive adjective"),
|
||||
"mine": ("1st person", ("neutral", "male", "female"), "possessive pronoun"),
|
||||
"myself": ("1st person", ("neutral", "male", "female"), "reflexive pronoun"),
|
||||
"we": ("1st person", "plural", "subject pronoun"),
|
||||
"us": ("1st person", "plural", "object pronoun"),
|
||||
"our": ("1st person", "plural", "possessive adjective"),
|
||||
"ours": ("1st person", "plural", "possessive pronoun"),
|
||||
"ourselves": ("1st person", "plural", "reflexive pronoun"),
|
||||
"you": (
|
||||
"2nd person",
|
||||
("neutral", "male", "female", "plural"),
|
||||
("subject pronoun", "object pronoun")
|
||||
),
|
||||
"your": (
|
||||
"2nd person",
|
||||
("neutral", "male", "female", "plural"),
|
||||
"possessive adjective"
|
||||
),
|
||||
"yours": (
|
||||
"2nd person",
|
||||
("neutral", "male", "female", "plural"),
|
||||
"possessive pronoun"
|
||||
),
|
||||
"yourself": (
|
||||
"2nd person",
|
||||
("neutral", "male", "female"),
|
||||
"reflexive pronoun"
|
||||
),
|
||||
"yourselves": (
|
||||
"2nd person",
|
||||
"plural",
|
||||
"reflexive pronoun"
|
||||
),
|
||||
"he": (
|
||||
"3rd person",
|
||||
"male",
|
||||
"subject pronoun"
|
||||
),
|
||||
"him": (
|
||||
"3rd person",
|
||||
"male",
|
||||
"object pronoun"
|
||||
),
|
||||
"his":(
|
||||
"3rd person",
|
||||
"male",
|
||||
("possessive pronoun","possessive adjective"),
|
||||
),
|
||||
"himself": (
|
||||
"3rd person",
|
||||
"male",
|
||||
"reflexive pronoun"
|
||||
),
|
||||
"she": (
|
||||
"3rd person",
|
||||
"female",
|
||||
"subject pronoun"
|
||||
),
|
||||
"2nd person",
|
||||
("neutral", "male", "female", "plural"),
|
||||
("subject pronoun", "object pronoun"),
|
||||
),
|
||||
"your": ("2nd person", ("neutral", "male", "female", "plural"), "possessive adjective"),
|
||||
"yours": ("2nd person", ("neutral", "male", "female", "plural"), "possessive pronoun"),
|
||||
"yourself": ("2nd person", ("neutral", "male", "female"), "reflexive pronoun"),
|
||||
"yourselves": ("2nd person", "plural", "reflexive pronoun"),
|
||||
"he": ("3rd person", "male", "subject pronoun"),
|
||||
"him": ("3rd person", "male", "object pronoun"),
|
||||
"his": (
|
||||
"3rd person",
|
||||
"male",
|
||||
("possessive pronoun", "possessive adjective"),
|
||||
),
|
||||
"himself": ("3rd person", "male", "reflexive pronoun"),
|
||||
"she": ("3rd person", "female", "subject pronoun"),
|
||||
"her": (
|
||||
"3rd person",
|
||||
"female",
|
||||
("object pronoun", "possessive adjective"),
|
||||
),
|
||||
"hers": (
|
||||
"3rd person",
|
||||
"female",
|
||||
"possessive pronoun"
|
||||
),
|
||||
"herself": (
|
||||
"3rd person",
|
||||
"female",
|
||||
"reflexive pronoun"
|
||||
),
|
||||
"3rd person",
|
||||
"female",
|
||||
("object pronoun", "possessive adjective"),
|
||||
),
|
||||
"hers": ("3rd person", "female", "possessive pronoun"),
|
||||
"herself": ("3rd person", "female", "reflexive pronoun"),
|
||||
"it": (
|
||||
"3rd person",
|
||||
"neutral",
|
||||
("subject pronoun", "object pronoun"),
|
||||
),
|
||||
"3rd person",
|
||||
"neutral",
|
||||
("subject pronoun", "object pronoun"),
|
||||
),
|
||||
"its": (
|
||||
"3rd person",
|
||||
"neutral",
|
||||
("possessive pronoun", "possessive adjective"),
|
||||
),
|
||||
"itself": (
|
||||
"3rd person",
|
||||
"neutral",
|
||||
"reflexive pronoun"
|
||||
),
|
||||
"they": (
|
||||
"3rd person",
|
||||
"plural",
|
||||
"subject pronoun"
|
||||
),
|
||||
"them": (
|
||||
"3rd person",
|
||||
"plural",
|
||||
"object pronoun"
|
||||
),
|
||||
"their": (
|
||||
"3rd person",
|
||||
"plural",
|
||||
"possessive adjective"
|
||||
),
|
||||
"theirs": (
|
||||
"3rd person",
|
||||
"plural",
|
||||
"possessive pronoun"
|
||||
),
|
||||
"themselves": (
|
||||
"3rd person",
|
||||
"plural",
|
||||
"reflexive pronoun"
|
||||
),
|
||||
"3rd person",
|
||||
"neutral",
|
||||
("possessive pronoun", "possessive adjective"),
|
||||
),
|
||||
"itself": ("3rd person", "neutral", "reflexive pronoun"),
|
||||
"they": ("3rd person", "plural", "subject pronoun"),
|
||||
"them": ("3rd person", "plural", "object pronoun"),
|
||||
"their": ("3rd person", "plural", "possessive adjective"),
|
||||
"theirs": ("3rd person", "plural", "possessive pronoun"),
|
||||
"themselves": ("3rd person", "plural", "reflexive pronoun"),
|
||||
}
|
||||
|
||||
# define the default viewpoint conversions
|
||||
|
|
@ -304,7 +186,11 @@ ALIASES = {
|
|||
|
||||
|
||||
def pronoun_to_viewpoints(
|
||||
pronoun, options=None, pronoun_type=DEFAULT_PRONOUN_TYPE, gender=DEFAULT_GENDER, viewpoint=DEFAULT_VIEWPOINT
|
||||
pronoun,
|
||||
options=None,
|
||||
pronoun_type=DEFAULT_PRONOUN_TYPE,
|
||||
gender=DEFAULT_GENDER,
|
||||
viewpoint=DEFAULT_VIEWPOINT,
|
||||
):
|
||||
"""
|
||||
Access function for determining the forms of a pronount from different viewpoints.
|
||||
|
|
@ -365,7 +251,7 @@ def pronoun_to_viewpoints(
|
|||
viewpoint = DEFAULT_VIEWPOINT
|
||||
if gender not in GENDERS:
|
||||
gender = DEFAULT_GENDER
|
||||
|
||||
|
||||
if options:
|
||||
# option string/list will override the kwargs differentiators given
|
||||
if isinstance(options, str):
|
||||
|
|
@ -395,9 +281,9 @@ def pronoun_to_viewpoints(
|
|||
|
||||
# special handling for the royal "we"
|
||||
if is_iter(source_gender):
|
||||
gender_opts = list(source_gender)
|
||||
gender_opts = list(source_gender)
|
||||
else:
|
||||
gender_opts = [source_gender]
|
||||
gender_opts = [source_gender]
|
||||
if viewpoint == "1st person":
|
||||
# make sure plural is always an option when converting to 1st person
|
||||
# it doesn't matter if it's in the list twice, so don't bother checking
|
||||
|
|
@ -409,7 +295,7 @@ def pronoun_to_viewpoints(
|
|||
viewpoint_map = PRONOUN_MAPPING[viewpoint]
|
||||
pronouns = viewpoint_map.get(pronoun_type, viewpoint_map[DEFAULT_PRONOUN_TYPE])
|
||||
mapped_pronoun = pronouns.get(gender, pronouns[DEFAULT_GENDER])
|
||||
|
||||
|
||||
# keep the same capitalization as the original
|
||||
if pronoun != "I":
|
||||
# don't remap I, since this is always capitalized.
|
||||
|
|
|
|||
|
|
@ -279,7 +279,7 @@ class TestPronounMapping(TestCase):
|
|||
("you", "m", "you", "he"),
|
||||
("you", "f op", "you", "her"),
|
||||
("I", "", "I", "it"),
|
||||
("I", "p", "I", "it"), # plural is invalid
|
||||
("I", "p", "I", "it"), # plural is invalid
|
||||
("I", "m", "I", "he"),
|
||||
("Me", "n", "Me", "It"),
|
||||
("your", "p", "your", "their"),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue