Ran formatting on code

This commit is contained in:
Griatch 2022-10-31 20:43:27 +01:00
parent 83154de19e
commit 353e4c0aa7
20 changed files with 296 additions and 327 deletions

View file

@ -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.')

View file

@ -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):

View file

@ -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"

View file

@ -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:

View file

@ -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

View file

@ -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"),
}
@ -110,7 +110,7 @@ class Map(object):
for row in range(self.max_length):
board.append([])
for column in range(int(self.max_width / 5)):
board[row].extend([' ', ' ', ' '])
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
@ -205,16 +207,16 @@ class Map(object):
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):

View file

@ -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")

View file

@ -1421,14 +1421,17 @@ 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()
class TestXyzExit(xyzroom.XYZExit):
def at_object_creation(self):
mock_exit_callbacks.at_object_creation()
MAP_DATA = {
"map": """
@ -1449,13 +1452,14 @@ MAP_DATA = {
("*", "*", "*"): {
"desc": "A passage.",
"prototype_parent": "xyz_exit",
}
},
},
"options": {
"map_visual_range": 1,
"map_mode": "scan",
},
}
}
class TestCallbacks(BaseEvenniaTest):
def setUp(self):
@ -1468,6 +1472,7 @@ class TestCallbacks(BaseEvenniaTest):
def _log(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()]
)

View file

@ -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)

View file

@ -7,6 +7,7 @@ from evennia.server.sessionhandler import SESSIONS
import git
import datetime
class GitCommand(MuxCommand):
"""
The shared functionality between git/git evennia
@ -22,23 +23,27 @@ class GitCommand(MuxCommand):
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
@ -62,8 +67,12 @@ class GitCommand(MuxCommand):
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)}
if changedFiles:
@ -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.")
@ -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,6 +154,7 @@ 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.

View file

@ -11,6 +11,7 @@ import git
import mock
import datetime
class TestGitIntegration(EvenniaTest):
@mock.patch("git.Repo")
@mock.patch("git.Git")
@ -48,8 +49,12 @@ class TestGitIntegration(EvenniaTest):
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):
@ -65,5 +70,6 @@ class TestGitIntegration(EvenniaTest):
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()}"
)

View file

@ -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):
"""

View file

@ -6,5 +6,6 @@ dependencies.
from evennia import nonexistent_module, DefaultScript
class BrokenScript(DefaultScript):
pass

View file

@ -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,20 +54,28 @@ 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()
@ -69,9 +83,16 @@ class TestGlobalScriptContainer(unittest.TestCase):
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()
@ -79,4 +100,7 @@ class TestGlobalScriptContainer(unittest.TestCase):
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,
)

View file

@ -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")

View file

@ -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)
@ -162,7 +164,11 @@ class TextToHTMLparser(object):
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():]
return (
text[: m.start()]
+ f'<a href="{href}" target="_blank">{label}</a>{rest}'
+ text[m.end() :]
)
else:
return text

View file

@ -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,126 +100,45 @@ 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"
("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"
),
"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"
),
"hers": ("3rd person", "female", "possessive pronoun"),
"herself": ("3rd person", "female", "reflexive pronoun"),
"it": (
"3rd person",
"neutral",
@ -243,36 +149,12 @@ PRONOUN_TABLE = {
"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"
),
"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.