Merge pull request #2903 from InspectorCaracal/refactor-pronouns

Refactor `pronouns.py`
This commit is contained in:
Griatch 2022-10-11 23:39:11 +02:00 committed by GitHub
commit 5f951de286
2 changed files with 259 additions and 239 deletions

View file

@ -2,7 +2,7 @@
English pronoun mapping between 1st/2nd person and 3rd person perspective (and vice-versa). English pronoun mapping between 1st/2nd person and 3rd person perspective (and vice-versa).
This file is released under the Evennia regular BSD License. This file is released under the Evennia regular BSD License.
(Griatch 2021) (Griatch 2021) - revised by InspectorCaracal 2022
Pronouns are words you use instead of a proper name, such as 'him', 'herself', 'theirs' etc. These Pronouns are words you use instead of a proper name, such as 'him', 'herself', 'theirs' etc. These
look different depending on who sees the outgoing string. This mapping maps between 1st/2nd case and look different depending on who sees the outgoing string. This mapping maps between 1st/2nd case and
@ -21,227 +21,266 @@ viewpoint/pronouns Subject Object Possessive Possessive Reflexive
3rd person male he him his his himself 3rd person male he him his his himself
3rd person female she her her hers herself 3rd person female she her her hers herself
3rd person neutral it it its theirs* itself 3rd person neutral it it its its itself
3rd person plural they them their theirs themselves 3rd person plural they them their theirs themselves
==================== ======= ======== ========== ========== =========== ==================== ======= ======== ========== ========== ===========
> `*`) Not formally used, we use `theirs` here as a filler.
""" """
from evennia.utils.utils import copy_word_case from evennia.utils.utils import copy_word_case, is_iter
DEFAULT_PRONOUN_TYPE = "object_pronoun" DEFAULT_PRONOUN_TYPE = "subject pronoun"
DEFAULT_VIEWPOINT = "2nd person" DEFAULT_VIEWPOINT = "2nd person"
DEFAULT_GENDER = "neutral" DEFAULT_GENDER = "neutral"
PRONOUN_TYPES = [
"subject pronoun",
"object pronoun",
"possessive adjective",
"possessive pronoun",
"reflexive pronoun",
]
VIEWPOINTS = ["1st person", "2nd person", "3rd person"]
GENDERS = ["male", "female", "neutral", "plural"]
PRONOUN_MAPPING = { PRONOUN_MAPPING = {
# 1st/2nd person -> 3rd person mappings "1st person": {
"I": {"subject pronoun": {"3rd person": {"male": "he", "female": "she", "neutral": "it"}}},
"me": {"object pronoun": {"3rd person": {"male": "him", "female": "her", "neutral": "it"}}},
"my": {
"possessive adjective": {"3rd person": {"male": "his", "female": "her", "neutral": "its"}}
},
"mine": {
"possessive pronoun": {
"3rd person": {
"male": "his",
"female": "hers",
"neutral": "theirs", # colloqial,
}
}
},
"myself": {
"reflexive_pronoun": {
"3rd person": {
"male": "himself",
"female": "herself",
"neutral": "itself",
"plural": "themselves",
}
}
},
"you": {
"subject pronoun": { "subject pronoun": {
"3rd person": { "neutral": "I",
"male": "he", "plural": "we",
"female": "she",
"neutral": "it",
"plural": "they",
}
}, },
"object pronoun": { "object pronoun": {
"3rd person": { "neutral": "me",
"male": "him", "plural": "us",
"female": "her",
"neutral": "it",
"plural": "them",
}
}, },
},
"your": {
"possessive adjective": { "possessive adjective": {
"3rd person": { "neutral": "my",
"male": "his", "plural": "our",
"female": "her",
"neutral": "its",
"plural": "their",
}
}
},
"yours": {
"possessive pronoun": {
"3rd person": {
"male": "his",
"female": "hers",
"neutral": "theirs", # colloqial
"plural": "theirs",
}
}
},
"yourself": {
"reflexive_pronoun": {
"3rd person": {
"male": "himself",
"female": "herself",
"neutral": "itself",
}
}
},
"we": {"subject pronoun": {"3rd person": {"plural": "they"}}},
"us": {"object pronoun": {"3rd person": {"plural": "them"}}},
"our": {"possessive adjective": {"3rd person": {"plural": "their"}}},
"ours": {"possessive pronoun": {"3rd person": {"plural": "theirs"}}},
"ourselves": {"reflexive pronoun": {"3rd person": {"plural": "themselves"}}},
"ours": {"possessive pronoun": {"3rd person": {"plural": "theirs"}}},
"ourselves": {"reflexive pronoun": {"3rd person": {"plural": "themselves"}}},
"yourselves": {"reflexive_pronoun": {"3rd person": {"plural": "themselves"}}},
# 3rd person to 1st/second person mappings
"he": {
"subject pronoun": {
"1st person": {"neutral": "I", "plural": "we"}, # pluralis majestatis
"2nd person": {"neutral": "you", "plural": "you"}, # pluralis majestatis
}
},
"him": {
"object pronoun": {
"1st person": {"neutral": "me", "plural": "us"}, # pluralis majestatis
"2nd person": {"neutral": "you", "plural": "you"}, # pluralis majestatis
}
},
"his": {
"possessive adjective": {
"1st person": {"neutral": "my", "plural": "our"}, # pluralis majestatis
"2nd person": {"neutral": "your", "plural": "your"}, # pluralis majestatis
}, },
"possessive pronoun": { "possessive pronoun": {
"1st person": {"neutral": "mine", "plural": "ours"}, # pluralis majestatis "neutral": "mine",
"2nd person": {"neutral": "yours", "plural": "yours"}, # pluralis majestatis "plural": "ours",
}, },
},
"himself": {
"reflexive pronoun": { "reflexive pronoun": {
"1st person": {"neutral": "myself", "plural": "ourselves"}, # pluralis majestatis "neutral": "myself",
"2nd person": {"neutral": "yours", "plural": "yours"}, # pluralis majestatis "plural": "ourselves"
},
},
"she": {
"subject pronoun": {
"1st person": {"neutral": "I", "plural": "you"}, # pluralis majestatis
"2nd person": {"neutral": "you", "plural": "we"}, # pluralis majestatis
} }
}, },
"her": { "2nd person": {
"subject pronoun": {
"neutral": "you",
},
"object pronoun": { "object pronoun": {
"1st person": {"neutral": "me", "plural": "us"}, # pluralis majestatis "neutral": "you",
"2nd person": {"neutral": "you", "plural": "you"}, # pluralis majestatis
}, },
"possessive adjective": { "possessive adjective": {
"1st person": {"neutral": "my", "plural": "our"}, # pluralis majestatis "neutral": "your",
"2nd person": {"neutral": "your", "plural": "your"}, # pluralis majestatis
}, },
},
"hers": {
"possessive pronoun": { "possessive pronoun": {
"1st person": {"neutral": "mine", "plural": "ours"}, # pluralis majestatis "neutral": "yours",
"2nd person": {"neutral": "yours", "plural": "yours"}, # pluralis majestatis },
"reflexive pronoun": {
"neutral": "yourself",
"plural": "yourselves",
} }
}, },
"herself": { "3rd person": {
"reflexive pronoun": {
"1st person": {"neutral": "myself", "plural": "ourselves"}, # pluralis majestatis
"2nd person": {"neutral": "yourself", "plural": "yourselves"}, # pluralis majestatis
},
},
"it": {
"subject pronoun": { "subject pronoun": {
"1st person": {"neutral": "I", "plural": "we"}, # pluralis majestatis "male": "he",
"2nd person": {"neutral": "you", "plural": "you"}, # pluralis majestatis "female": "she",
"neutral": "it",
"plural": "they"
}, },
"object pronoun": { "object pronoun": {
"1st person": {"neutral": "me", "plural": "us"}, # pluralis majestatis "male": "him",
"2nd person": {"neutral": "you", "plural": "you"}, # pluralis majestatis "female": "her",
"neutral": "it",
"plural": "them"
}, },
},
"its": {
"possessive adjective": { "possessive adjective": {
"1st person": {"neutral": "my", "plural": "our"}, # pluralis majestatis "male": "his",
"2nd person": {"neutral": "your", "plural": "your"}, # pluralis majestatis "female": "her",
} "neutral": "its",
}, "plural": "their"
"theirs": { },
"possessive pronoun": { "possessive pronoun": {
"1st person": {"neutral": "mine", "plural": "ours"}, # pluralis majestatis "male": "his",
"2nd person": {"neutral": "yours", "plural": "yours"}, # pluralis majestatis "female": "hers",
} "neutral": "its",
}, "plural": "theirs",
"itself": {
"reflexive pronoun": {
"1st person": {"neutral": "myself", "plural": "ourselves"}, # pluralis majestatis
"2nd person": {"neutral": "yourself", "plural": "yourselves"}, # pluralis majestatis
}, },
},
"they": {
"subject pronoun": {
"1st person": {
"plural": "we",
},
"2nd person": {
"plural": "you",
},
}
},
"them": {
"object pronoun": {
"1st person": {
"plural": "us",
},
"2nd person": {
"plural": "you",
},
}
},
"their": {
"possessive adjective": {
"1st person": {
"plural": "our",
},
"2nd person": {
"plural": "your",
},
}
},
"themselves": {
"reflexive pronoun": { "reflexive pronoun": {
"1st person": { "male": "himself",
"plural": "ourselves", "female": "herself",
}, "neutral": "itself",
"2nd person": { "plural": "themselves",
"plural": "yourselves", },
}, }
}
},
} }
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"
),
"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"
),
"her": (
"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"),
),
"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"
),
}
# define the default viewpoint conversions
VIEWPOINT_CONVERSION = {
"1st person": "3rd person",
"2nd person": "3rd person",
"3rd person": ("1st person", "2nd person"),
}
ALIASES = { ALIASES = {
"m": "male", "m": "male",
@ -263,19 +302,9 @@ ALIASES = {
"pp": "possessive pronoun", "pp": "possessive pronoun",
} }
PRONOUN_TYPES = [
"subject pronoun",
"object pronoun",
"possessive adjective",
"possessive pronoun",
"reflexive pronoun",
]
VIEWPOINTS = ["1st person", "2nd person", "3rd person"]
GENDERS = ["male", "female", "neutral", "plural"] # including plural as a gender for simplicity
def pronoun_to_viewpoints( def pronoun_to_viewpoints(
pronoun, options=None, pronoun_type="object_pronoun", gender="neutral", viewpoint="2nd person" 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. Access function for determining the forms of a pronount from different viewpoints.
@ -292,7 +321,7 @@ def pronoun_to_viewpoints(
- `subject pronoun`/`subject`/`sp` (I, you, he, they) - `subject pronoun`/`subject`/`sp` (I, you, he, they)
- `object pronoun`/`object/`/`op` (me, you, him, them) - `object pronoun`/`object/`/`op` (me, you, him, them)
- `possessive adjective`/`adjective`/`pa` (my, your, his, their) - `possessive adjective`/`adjective`/`pa` (my, your, his, their)
- `possessive pronoun`/`pronoun`/`pp` (mine, yours, his, theirs) - `possessive pronoun`/`pronoun`/`pp` (mine, yours, his, theirs)
gender (str, optional): Specific gender to use (plural counts a gender for this purpose). gender (str, optional): Specific gender to use (plural counts a gender for this purpose).
A gender specified in `options` takes precedence. Values and aliases are: A gender specified in `options` takes precedence. Values and aliases are:
@ -323,11 +352,13 @@ def pronoun_to_viewpoints(
pronoun_lower = "I" if pronoun == "I" else pronoun.lower() pronoun_lower = "I" if pronoun == "I" else pronoun.lower()
if pronoun_lower not in PRONOUN_MAPPING: if pronoun_lower not in PRONOUN_TABLE:
return pronoun return pronoun
# differentiators # get the default data for the input pronoun
source_viewpoint, source_gender, source_type = PRONOUN_TABLE[pronoun_lower]
# differentiators
if pronoun_type not in PRONOUN_TYPES: if pronoun_type not in PRONOUN_TYPES:
pronoun_type = DEFAULT_PRONOUN_TYPE pronoun_type = DEFAULT_PRONOUN_TYPE
if viewpoint not in VIEWPOINTS: if viewpoint not in VIEWPOINTS:
@ -350,43 +381,34 @@ def pronoun_to_viewpoints(
elif opt in GENDERS: elif opt in GENDERS:
gender = opt gender = opt
# step down into the mapping, using differentiators as needed # check if pronoun maps to multiple options and differentiate
pronoun_types = PRONOUN_MAPPING[pronoun_lower] # but don't allow invalid differentiators
# this has one or more pronoun-types if is_iter(source_type):
if len(pronoun_types) == 1: pronoun_type = pronoun_type if pronoun_type in source_type else source_type[0]
pronoun_type, viewpoints = next(iter(pronoun_types.items()))
elif pronoun_type in pronoun_types:
viewpoints = pronoun_types[pronoun_type]
elif DEFAULT_PRONOUN_TYPE in pronoun_types:
pronoun_type = DEFAULT_PRONOUN_TYPE
viewpoints = pronoun_types[pronoun_type]
else: else:
# not enough info - grab the first of the mappings pronoun_type = source_type
pronoun_type, viewpoints = next(iter(pronoun_types.items())) target_viewpoint = VIEWPOINT_CONVERSION[source_viewpoint]
if is_iter(target_viewpoint):
viewpoint = viewpoint if viewpoint in target_viewpoint else target_viewpoint[0]
else:
viewpoint = target_viewpoint
# we have one or more viewpoints at this point # special handling for the royal "we"
if len(viewpoints) == 1: if is_iter(source_gender):
viewpoint, genders = next(iter(viewpoints.items())) gender_opts = list(source_gender)
elif viewpoint in viewpoints:
genders = viewpoints[viewpoint]
elif DEFAULT_VIEWPOINT in viewpoints:
viewpoint = DEFAULT_VIEWPOINT
genders = viewpoints[viewpoint]
else: else:
# not enough info - grab first of mappings gender_opts = [source_gender]
viewpoint, genders = next(iter(viewpoints.items())) 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
gender_opts.append("plural")
# if the gender is still not in the extended options, fall back to source pronoun's default
gender = gender if gender in gender_opts else gender_opts[0]
# we have one or more possible genders (including plural forms) # step down into the mapping
if len(genders) == 1: viewpoint_map = PRONOUN_MAPPING[viewpoint]
gender, mapped_pronoun = next(iter(genders.items())) pronouns = viewpoint_map.get(pronoun_type, viewpoint_map[DEFAULT_PRONOUN_TYPE])
elif gender in genders: mapped_pronoun = pronouns.get(gender, pronouns[DEFAULT_GENDER])
mapped_pronoun = genders[gender]
elif DEFAULT_GENDER in genders:
gender = DEFAULT_GENDER
mapped_pronoun = genders[gender]
else:
# not enough info - grab first mapping
gender, mapped_pronoun = next(iter(genders.items()))
# keep the same capitalization as the original # keep the same capitalization as the original
if pronoun != "I": if pronoun != "I":
@ -396,10 +418,10 @@ def pronoun_to_viewpoints(
mapped_pronoun = mapped_pronoun.upper() mapped_pronoun = mapped_pronoun.upper()
if viewpoint == "3rd person": if viewpoint == "3rd person":
# the remapped viewpoing is in 3rd person, meaning the ingoing viewpoing # the desired viewpoint is 3rd person, meaning the incoming viewpoint
# must have been 1st or 2nd person. # must have been 1st or 2nd person.
return pronoun, mapped_pronoun return pronoun, mapped_pronoun
else: else:
# the remapped viewpoint is 1st or 2nd person, so ingoing must have been # the desired viewpoint is 1st or 2nd person, so incoming must have been
# in 3rd person form. # in 3rd person form.
return mapped_pronoun, pronoun return mapped_pronoun, pronoun

View file

@ -279,7 +279,7 @@ class TestPronounMapping(TestCase):
("you", "m", "you", "he"), ("you", "m", "you", "he"),
("you", "f op", "you", "her"), ("you", "f op", "you", "her"),
("I", "", "I", "it"), ("I", "", "I", "it"),
("I", "p", "I", "it"), # plural is invalid ("I", "p", "I", "it"), # plural is invalid
("I", "m", "I", "he"), ("I", "m", "I", "he"),
("Me", "n", "Me", "It"), ("Me", "n", "Me", "It"),
("your", "p", "your", "their"), ("your", "p", "your", "their"),
@ -295,7 +295,6 @@ class TestPronounMapping(TestCase):
("her", "p", "you", "her"), ("her", "p", "you", "her"),
("her", "pa", "your", "her"), ("her", "pa", "your", "her"),
("their", "pa", "your", "their"), ("their", "pa", "your", "their"),
("their", "pa", "your", "their"),
("itself", "", "yourself", "itself"), ("itself", "", "yourself", "itself"),
("themselves", "", "yourselves", "themselves"), ("themselves", "", "yourselves", "themselves"),
("herself", "", "yourself", "herself"), ("herself", "", "yourself", "herself"),
@ -311,6 +310,5 @@ class TestPronounMapping(TestCase):
received_1st_or_2nd_person, received_3rd_person = pronouns.pronoun_to_viewpoints( received_1st_or_2nd_person, received_3rd_person = pronouns.pronoun_to_viewpoints(
pronoun, options pronoun, options
) )
self.assertEqual(expected_1st_or_2nd_person, received_1st_or_2nd_person) self.assertEqual(expected_1st_or_2nd_person, received_1st_or_2nd_person)
self.assertEqual(expected_3rd_person, received_3rd_person) self.assertEqual(expected_3rd_person, received_3rd_person)