alessandro trinca tornidor commited on
Commit
e0b1feb
·
1 Parent(s): 5012c50

feat: add /words-frequency POST route to return a wordsapi compatible response from nltk wordnet corpus

Browse files
my_ghost_writer/app.py CHANGED
@@ -21,6 +21,7 @@ from my_ghost_writer.constants import (app_logger, ALLOWED_ORIGIN_LIST, API_MODE
21
  from my_ghost_writer.pymongo_utils import mongodb_health_check
22
  from my_ghost_writer.text_parsers import text_stemming
23
  from my_ghost_writer.type_hints import RequestTextFrequencyBody, RequestQueryThesaurusWordsapiBody
 
24
 
25
 
26
  async def mongo_health_check_background_task():
@@ -28,7 +29,7 @@ async def mongo_health_check_background_task():
28
  while ME_CONFIG_MONGODB_USE_OK:
29
  try:
30
  db_ok["mongo_ok"] = health_mongo() == "Mongodb: still alive..."
31
- except PyMongoError:
32
  db_ok["mongo_ok"] = False
33
  await asyncio.sleep(ME_CONFIG_MONGODB_HEALTHCHECK_SLEEP)
34
 
@@ -72,6 +73,17 @@ def health():
72
  return "Still alive..."
73
 
74
 
 
 
 
 
 
 
 
 
 
 
 
75
  @app.get("/health-mongo")
76
  def health_mongo() -> str:
77
  app_logger.info(f"pymongo driver version:{pymongo_version}!")
@@ -107,6 +119,32 @@ def get_words_frequency(body: RequestTextFrequencyBody | str) -> JSONResponse:
107
  return JSONResponse(status_code=200, content=content_response)
108
 
109
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
110
  @app.post("/thesaurus-wordsapi")
111
  def get_thesaurus_wordsapi(body: RequestQueryThesaurusWordsapiBody | str) -> JSONResponse:
112
  t0 = datetime.now()
 
21
  from my_ghost_writer.pymongo_utils import mongodb_health_check
22
  from my_ghost_writer.text_parsers import text_stemming
23
  from my_ghost_writer.type_hints import RequestTextFrequencyBody, RequestQueryThesaurusWordsapiBody
24
+ from my_ghost_writer.thesaurus import get_current_info_wordnet, get_synsets_by_word_and_language
25
 
26
 
27
  async def mongo_health_check_background_task():
 
29
  while ME_CONFIG_MONGODB_USE_OK:
30
  try:
31
  db_ok["mongo_ok"] = health_mongo() == "Mongodb: still alive..."
32
+ except (PyMongoError, HTTPException):
33
  db_ok["mongo_ok"] = False
34
  await asyncio.sleep(ME_CONFIG_MONGODB_HEALTHCHECK_SLEEP)
35
 
 
73
  return "Still alive..."
74
 
75
 
76
+ @app.get("/health-wordnet")
77
+ def get_wordnet_languages():
78
+ try:
79
+ info = get_current_info_wordnet()
80
+ return JSONResponse(status_code=200, content={"msg": info})
81
+ except Exception as e:
82
+ app_logger.error("exception:")
83
+ app_logger.error(e)
84
+ raise HTTPException(status_code=503, detail=str(type(e)))
85
+
86
+
87
  @app.get("/health-mongo")
88
  def health_mongo() -> str:
89
  app_logger.info(f"pymongo driver version:{pymongo_version}!")
 
119
  return JSONResponse(status_code=200, content=content_response)
120
 
121
 
122
+ @app.post("/thesaurus-wordnet")
123
+ def get_thesaurus_wordnet(body: RequestQueryThesaurusWordsapiBody | str) -> JSONResponse:
124
+ t0 = datetime.now()
125
+ app_logger.info(f"body type: {type(body)} => {body}.")
126
+ body_validated = RequestQueryThesaurusWordsapiBody.model_validate_json(body)
127
+ query = body_validated.query
128
+ app_logger.info(f"query: {type(query)} => {query}, starting get_synsets_by_word_and_language...")
129
+ use_mongo: bool = db_ok["mongo_ok"]
130
+ app_logger.info(f"query: {type(query)} => {query}, use mongo? {use_mongo}.")
131
+ if use_mongo:
132
+ try:
133
+ response = pymongo_operations_rw.get_document_by_word(query=query)
134
+ t1 = datetime.now()
135
+ duration = (t1 - t0).total_seconds()
136
+ app_logger.info(f"found local data, duration: {duration:.3f}s.")
137
+ return JSONResponse(status_code=200, content={"duration": duration, "thesaurus": response, "source": "local"})
138
+ except (PyMongoError, AssertionError) as pme:
139
+ app_logger.info(f"{pme}! Let's try the remote service...")
140
+
141
+ response = get_synsets_by_word_and_language(query, lang="eng")
142
+ t1 = datetime.now()
143
+ duration = (t1 - t0).total_seconds()
144
+ app_logger.info(f"response.status_code: {response.status_code}, duration: {duration:.3f}s.")
145
+ return JSONResponse(status_code=200, content={"duration": duration, "thesaurus": response, "source": "wordnet"})
146
+
147
+
148
  @app.post("/thesaurus-wordsapi")
149
  def get_thesaurus_wordsapi(body: RequestQueryThesaurusWordsapiBody | str) -> JSONResponse:
150
  t0 = datetime.now()
my_ghost_writer/constants.py CHANGED
@@ -20,6 +20,7 @@ IS_TESTING = bool(os.getenv('IS_TESTING', ""))
20
  LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO")
21
  API_MODE = bool(os.getenv("API_MODE", ""))
22
  N_WORDS_GRAM = int(os.getenv("N_WORDS_GRAM", 2))
 
23
  WORDSAPI_KEY = os.getenv("WORDSAPI_KEY")
24
  WORDSAPI_URL = os.getenv("WORDSAPI_URL", "https://wordsapiv1.p.rapidapi.com/words")
25
  RAPIDAPI_HOST = os.getenv("RAPIDAPI_HOST", "wordsapiv1.p.rapidapi.com")
 
20
  LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO")
21
  API_MODE = bool(os.getenv("API_MODE", ""))
22
  N_WORDS_GRAM = int(os.getenv("N_WORDS_GRAM", 2))
23
+ WORDNET_LANGUAGES=(os.getenv("WORDNET_LANGUAGES", "eng,"))
24
  WORDSAPI_KEY = os.getenv("WORDSAPI_KEY")
25
  WORDSAPI_URL = os.getenv("WORDSAPI_URL", "https://wordsapiv1.p.rapidapi.com/words")
26
  RAPIDAPI_HOST = os.getenv("RAPIDAPI_HOST", "wordsapiv1.p.rapidapi.com")
my_ghost_writer/thesaurus.py ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Any
2
+
3
+ from nltk.corpus import wordnet31 as wn
4
+
5
+ from my_ghost_writer.type_hints import ResponseWordsAPI
6
+
7
+
8
+ def get_current_info_wordnet():
9
+ return {"languages": wn.langs(), "version": wn.get_version()}
10
+
11
+
12
+ def get_synsets_by_word_and_language(word: str, lang: str = "eng") -> ResponseWordsAPI:
13
+ results = []
14
+ for synset in wn.synsets(word, lang=lang):
15
+ # Synonyms (lemmas for this synset, excluding the input word)
16
+ synonyms = sorted(
17
+ set(
18
+ l.name().replace('_', ' ')
19
+ for l in synset.lemmas(lang=lang)
20
+ if l.name().lower() != word.lower()
21
+ )
22
+ )
23
+ # Antonyms (from lemmas)
24
+ antonyms = sorted(
25
+ set(
26
+ ant.name().replace('_', ' ')
27
+ for l in synset.lemmas(lang=lang)
28
+ for ant in l.antonyms()
29
+ )
30
+ )
31
+ # Derivationally related forms (from lemmas)
32
+ derivation = sorted(
33
+ set(
34
+ d.name().replace('_', ' ')
35
+ for l in synset.lemmas(lang=lang)
36
+ for d in l.derivationally_related_forms()
37
+ )
38
+ )
39
+ # Pertainyms (from lemmas)
40
+ pertains_to = sorted(
41
+ set(
42
+ p.name().replace('_', ' ')
43
+ for l in synset.lemmas(lang=lang)
44
+ for p in l.pertainyms()
45
+ )
46
+ )
47
+ # Synset relations
48
+ type_of = sorted(
49
+ set(
50
+ l.name().replace('_', ' ')
51
+ for h in synset.hypernyms()
52
+ for l in h.lemmas(lang=lang)
53
+ )
54
+ )
55
+ # Hyponyms (hasTypes)
56
+ has_types = sorted(
57
+ set(
58
+ l.name().replace('_', ' ')
59
+ for h in synset.hyponyms()
60
+ for l in h.lemmas(lang=lang)
61
+ )
62
+ )
63
+ # Holonyms (partOf)
64
+ part_of = sorted(
65
+ set(
66
+ l.name().replace('_', ' ')
67
+ for h in synset.member_holonyms() + synset.part_holonyms() + synset.substance_holonyms()
68
+ for l in h.lemmas(lang=lang)
69
+ )
70
+ )
71
+ # Meronyms (hasParts)
72
+ has_parts = sorted(
73
+ set(
74
+ l.name().replace('_', ' ')
75
+ for h in synset.member_meronyms() + synset.part_meronyms() + synset.substance_meronyms()
76
+ for l in h.lemmas(lang=lang)
77
+ )
78
+ )
79
+ instance_of = sorted(
80
+ set(
81
+ l.name().replace('_', ' ')
82
+ for h in synset.instance_hypernyms()
83
+ for l in h.lemmas(lang=lang)
84
+ )
85
+ )
86
+ has_instances = sorted(
87
+ set(
88
+ l.name().replace('_', ' ')
89
+ for h in synset.instance_hyponyms()
90
+ for l in h.lemmas(lang=lang)
91
+ )
92
+ )
93
+ similar_to = sorted(
94
+ set(
95
+ l.name().replace('_', ' ')
96
+ for h in synset.similar_tos()
97
+ for l in h.lemmas(lang=lang)
98
+ )
99
+ )
100
+ also = sorted(
101
+ set(
102
+ l.name().replace('_', ' ')
103
+ for h in synset.also_sees()
104
+ for l in h.lemmas(lang=lang)
105
+ )
106
+ )
107
+ entails = sorted(
108
+ set(
109
+ l.name().replace('_', ' ')
110
+ for h in synset.entailments()
111
+ for l in h.lemmas(lang=lang)
112
+ )
113
+ )
114
+ causes = sorted(
115
+ set(
116
+ l.name().replace('_', ' ')
117
+ for h in synset.causes()
118
+ for l in h.lemmas(lang=lang)
119
+ )
120
+ )
121
+ verb_groups = sorted(
122
+ set(
123
+ l.name().replace('_', ' ')
124
+ for h in synset.verb_groups()
125
+ for l in h.lemmas(lang=lang)
126
+ )
127
+ )
128
+ has_substances = sorted(
129
+ set(
130
+ l.name().replace('_', ' ')
131
+ for h in synset.substance_meronyms()
132
+ for l in h.lemmas(lang=lang)
133
+ )
134
+ )
135
+ in_category = sorted(
136
+ set(
137
+ l.name().replace('_', ' ')
138
+ for h in synset.topic_domains()
139
+ for l in h.lemmas(lang=lang)
140
+ )
141
+ )
142
+ usage_of = sorted(
143
+ set(
144
+ l.name().replace('_', ' ')
145
+ for h in synset.usage_domains()
146
+ for l in h.lemmas(lang=lang)
147
+ )
148
+ )
149
+ obj = {
150
+ "definition": synset.definition(lang=lang),
151
+ }
152
+ if synonyms:
153
+ obj["synonyms"] = synonyms
154
+ if type_of:
155
+ obj["typeOf"] = type_of
156
+ if has_types:
157
+ obj["hasTypes"] = has_types
158
+ if part_of:
159
+ obj["partOf"]: part_of
160
+ if has_parts:
161
+ obj["hasParts"]: has_parts
162
+ if antonyms:
163
+ obj["antonyms"] = antonyms
164
+ if derivation:
165
+ obj["derivation"] = derivation
166
+ if pertains_to:
167
+ obj["pertainsTo"] = pertains_to
168
+ if instance_of:
169
+ obj["instanceOf"] = instance_of
170
+ if has_instances:
171
+ obj["hasInstances"] = has_instances
172
+ if similar_to:
173
+ obj["similarTo"] = similar_to
174
+ if also:
175
+ obj["also"] = also
176
+ if entails:
177
+ obj["entails"] = entails
178
+ if has_substances:
179
+ obj["hasSubstances"] = has_substances
180
+ if in_category:
181
+ obj["inCategory"] = in_category
182
+ if usage_of:
183
+ obj["usageOf"] = usage_of
184
+ if causes:
185
+ obj["causes"] = causes
186
+ if verb_groups:
187
+ obj["verbGroups"] = verb_groups
188
+ results.append(obj)
189
+ return {
190
+ "word": word,
191
+ "results": results
192
+ }
193
+
194
+
195
+ if __name__ == '__main__':
196
+ res = {}
197
+ for w in ["dog", "spider", "look", "tree"]:
198
+ oo = get_synsets_by_word_and_language(w, lang="eng")
199
+ res[w] = oo
200
+ pass
my_ghost_writer/type_hints.py CHANGED
@@ -1,4 +1,4 @@
1
- from typing import TypedDict
2
  from pydantic import BaseModel
3
 
4
 
@@ -45,6 +45,34 @@ class WordStem(TypedDict):
45
  offsets_array: list[OffsetArray]
46
 
47
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  RequestTextRowsList = list[InputTextRow]
49
  RequestTextRowsParentList = list[InputTextRowWithParent]
50
  ResponseTextRowsDict = tuple[int, dict[str, WordStem]]
 
 
1
+ from typing import TypedDict, Optional
2
  from pydantic import BaseModel
3
 
4
 
 
45
  offsets_array: list[OffsetArray]
46
 
47
 
48
+ class ResultWordsAPI(TypedDict):
49
+ definition: str
50
+ synonyms: Optional[list[str]]
51
+ typeOf: Optional[list[str]]
52
+ hasTypes: Optional[list[str]]
53
+ partOf: Optional[list[str]]
54
+ hasParts: Optional[list[str]]
55
+ antonyms: Optional[list[str]]
56
+ derivation: Optional[list[str]]
57
+ pertainsTo: Optional[list[str]]
58
+ instanceOf: Optional[list[str]]
59
+ hasInstances: Optional[list[str]]
60
+ similarTo: Optional[list[str]]
61
+ also: Optional[list[str]]
62
+ entails: Optional[list[str]]
63
+ hasSubstances: Optional[list[str]]
64
+ inCategory: Optional[list[str]]
65
+ usageOf: Optional[list[str]]
66
+ causes: Optional[list[str]]
67
+ verbGroups: Optional[list[str]]
68
+
69
+
70
+ class ResponseWordsAPI(TypedDict):
71
+ word: str
72
+ results: list[ResultWordsAPI]
73
+
74
+
75
  RequestTextRowsList = list[InputTextRow]
76
  RequestTextRowsParentList = list[InputTextRowWithParent]
77
  ResponseTextRowsDict = tuple[int, dict[str, WordStem]]
78
+ #ResponseWordsAPI = dict[str, str | list[str]]
tests/events/expected_get_synsets_by_word_and_language_dog.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"word": "dog", "results": [{"definition": "a member of the genus Canis (probably descended from the common wolf) that has been domesticated by man since prehistoric times; occurs in many breeds", "synonyms": ["Canis familiaris", "domestic dog"], "typeOf": ["canid", "canine", "domestic animal", "domesticated animal"], "hasTypes": ["Belgian griffon", "Brussels griffon", "Great Pyrenees", "Leonberg", "Mexican hairless", "Newfoundland", "Newfoundland dog", "Welsh corgi", "barker", "basenji", "bow-wow", "carriage dog", "coach dog", "corgi", "cur", "dalmatian", "doggie", "doggy", "griffon", "hunting dog", "lapdog", "mongrel", "mutt", "pooch", "poodle", "poodle dog", "pug", "pug-dog", "puppy", "spitz", "toy", "toy dog", "working dog"]}, {"definition": "a dull unattractive unpleasant girl or woman", "synonyms": ["frump"], "typeOf": ["disagreeable woman", "unpleasant woman"], "derivation": ["frumpy"]}, {"definition": "informal term for a man", "typeOf": ["blighter", "bloke", "chap", "cuss", "fella", "feller", "fellow", "gent", "lad"]}, {"definition": "someone who is morally reprehensible", "synonyms": ["blackguard", "bounder", "cad", "heel", "hound"], "typeOf": ["scoundrel", "villain"], "hasTypes": ["perisher"], "derivation": ["blackguardly"]}, {"definition": "a smooth-textured sausage of minced beef or pork usually smoked; often served on a bread roll", "synonyms": ["frank", "frankfurter", "hot dog", "hotdog", "weenie", "wiener", "wienerwurst"], "typeOf": ["sausage"], "hasTypes": ["Vienna sausage"]}, {"definition": "a hinged catch that fits into a notch of a ratchet to move a wheel forward or prevent it from moving backward", "synonyms": ["click", "detent", "pawl"], "typeOf": ["catch", "stop"]}, {"definition": "metal supports for logs in a fireplace", "synonyms": ["andiron", "dog-iron", "firedog"], "typeOf": ["support"]}, {"definition": "go after with the intent to catch", "synonyms": ["chase", "chase after", "give chase", "go after", "tag", "tail", "track", "trail"], "typeOf": ["follow", "pursue"], "hasTypes": ["hound", "hunt", "quest", "run down", "trace", "tree"], "derivation": ["chase", "chaser", "tag", "tail", "tailing", "track", "tracker", "tracking", "trailing"]}]}
tests/events/expected_get_synsets_by_word_and_language_look.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"word": "look", "results": [{"definition": "the feelings expressed on a person's face", "synonyms": ["aspect", "expression", "face", "facial expression"], "typeOf": ["countenance", "visage"], "hasTypes": ["leer", "light", "spark", "sparkle", "twinkle"], "derivation": ["look"]}, {"definition": "the act of directing the eyes toward something and perceiving it visually", "synonyms": ["looking", "looking at"], "typeOf": ["perception", "sensing"], "hasTypes": ["coup d'oeil", "dekko", "evil eye", "glance", "glimpse", "lookout", "observance", "observation", "outlook", "peek", "peep", "rubber-necking", "scrutiny", "sight", "sightseeing", "squint", "stare", "survey", "view", "watching"], "derivation": ["look"]}, {"definition": "physical appearance", "typeOf": ["appearance", "visual aspect"], "derivation": ["look"]}, {"definition": "the general atmosphere of a place or situation and the effect that it has on people", "synonyms": ["feel", "feeling", "flavor", "flavour", "smell", "spirit", "tone"], "typeOf": ["ambiance", "ambience", "atmosphere"], "hasTypes": ["Hollywood", "Zeitgeist"], "derivation": ["feel", "look", "spirit", "spiritize"]}, {"definition": "perceive with attention; direct one's gaze towards", "hasTypes": ["admire", "consider", "eye", "eyeball", "gape", "gawk", "gawp", "gaze", "get a load", "give the eye", "give the glad eye", "give the once over", "glance", "glint", "gloat", "goggle", "have a look", "leer", "look around", "look away", "look back", "look backward", "ogle", "peek", "peep", "peer", "regard", "squint", "stare", "take a look"], "derivation": ["look", "looker"], "entails": ["see"]}, {"definition": "give a certain impression or have a certain outward aspect", "synonyms": ["appear", "seem"], "typeOf": ["be"], "hasTypes": ["beam", "come across", "cut", "feel", "gleam", "glint", "glisten", "glitter", "glow", "jump", "jump out", "leap out", "lift", "loom", "make", "pass off", "radiate", "rear", "rise", "shine", "sound", "stand out", "stick out"], "derivation": ["appearance", "look"]}, {"definition": "have a certain outward or facial expression", "typeOf": ["be"], "hasTypes": ["squint"], "derivation": ["look"]}, {"definition": "search or seek", "synonyms": ["search"], "typeOf": ["examine", "see"], "hasTypes": ["cruise", "horn in", "hunt", "intrude", "nose", "poke", "prospect", "pry"], "derivation": ["search", "searcher"]}, {"definition": "be oriented in a certain direction, often with respect to another reference point; be opposite to", "synonyms": ["face", "front"], "typeOf": ["lie"], "hasTypes": ["confront"], "antonyms": ["back"], "derivation": ["front", "frontage"], "verbGroups": ["face"]}, {"definition": "take charge of or deal with", "synonyms": ["attend", "see", "take care"], "typeOf": ["care", "give care"], "hasTypes": ["minister", "tend"], "derivation": ["attention"]}, {"definition": "convey by one's expression", "typeOf": ["convey"], "derivation": ["look"]}, {"definition": "look forward to the probable occurrence of", "synonyms": ["await", "expect", "wait"], "hasTypes": ["anticipate", "expect", "hang on", "hold on", "hold the line", "look for", "look forward", "look to"], "derivation": ["expectancy", "expectant", "expectation", "waiter"], "verbGroups": ["anticipate", "expect"]}, {"definition": "accord in appearance with", "typeOf": ["agree", "check", "correspond", "fit", "gibe", "jibe", "match", "tally"]}, {"definition": "have faith or confidence in", "synonyms": ["bank", "bet", "calculate", "count", "depend", "reckon", "rely", "swear"], "typeOf": ["trust"], "derivation": ["dependency", "reliance", "reliant"]}]}
tests/events/expected_get_synsets_by_word_and_language_power.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"word": "power", "results": [{"definition": "possession of controlling influence", "synonyms": ["powerfulness"], "typeOf": ["quality"], "hasTypes": ["chokehold", "control", "discretion", "disposal", "effectiveness", "effectivity", "effectuality", "effectualness", "free will", "influence", "interest", "interestingness", "irresistibility", "irresistibleness", "jurisdiction", "legal power", "persuasiveness", "potency", "preponderance", "puissance", "repellant", "repellent", "stranglehold", "strength", "sway", "throttlehold", "valence", "valency", "veto"], "antonyms": ["powerlessness"], "derivation": ["powerful"]}, {"definition": "(physics) the rate of doing work; measured in watts (= joules/second)", "typeOf": ["physical phenomenon"], "hasTypes": ["electric power", "electrical power", "waterpower", "wattage"], "derivation": ["power"], "inCategory": ["natural philosophy", "physics"]}, {"definition": "possession of the qualities (especially mental qualities) required to do something or get something done", "synonyms": ["ability"], "typeOf": ["cognition", "knowledge", "noesis"], "hasTypes": ["accomplishment", "acquirement", "acquisition", "aptitude", "attainment", "bilingualism", "capacity", "creative thinking", "creativeness", "creativity", "faculty", "hand", "intelligence", "know-how", "leadership", "mental ability", "mental faculty", "module", "originality", "science", "skill", "superior skill"], "antonyms": ["inability"], "derivation": ["able"]}, {"definition": "(of a government or government official) holding an office means being in power", "synonyms": ["office"], "typeOf": ["state"], "hasTypes": ["executive clemency", "war power"], "derivation": ["official", "officiate"], "inCategory": ["administration", "governance", "governing", "government", "government activity"]}, {"definition": "one possessing or exercising power or influence or authority", "synonyms": ["force"], "typeOf": ["causal agency", "causal agent", "cause"], "hasTypes": ["Moloch", "influence", "juggernaut", "steamroller"], "derivation": ["force"]}, {"definition": "a mathematical notation indicating the number of times a quantity is multiplied by itself", "synonyms": ["exponent", "index"], "typeOf": ["mathematical notation"], "hasTypes": ["degree", "log", "logarithm"], "derivation": ["exponential"]}, {"definition": "physical strength", "synonyms": ["might", "mightiness"], "typeOf": ["strength"], "derivation": ["mighty"]}, {"definition": "a state powerful enough to influence events throughout the world", "synonyms": ["great power", "major power", "superpower", "world power"], "typeOf": ["body politic", "commonwealth", "country", "land", "nation", "res publica", "state"], "hasTypes": ["hegemon"]}, {"definition": "energy made available by the flow of electric charge through a conductor", "synonyms": ["electrical energy", "electricity"], "typeOf": ["energy", "free energy"], "hasTypes": ["AC", "DC", "alternating current", "alternating electric current", "direct current", "direct electric current", "signal"], "derivation": ["electric", "electrify"]}, {"definition": "a very wealthy or powerful businessman", "synonyms": ["baron", "big businessman", "business leader", "king", "magnate", "mogul", "top executive", "tycoon"], "typeOf": ["businessman", "man of affairs"], "hasTypes": ["oil tycoon"]}, {"definition": "supply the force or power for the functioning of", "typeOf": ["cater", "ply", "provide", "supply"], "hasTypes": ["drive"], "derivation": ["power"]}]}
tests/events/expected_get_synsets_by_word_and_language_term.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"word": "term", "results": [{"definition": "a word or expression used for some particular thing", "typeOf": ["word"], "hasTypes": ["referent"], "derivation": ["term"]}, {"definition": "a limited period of time", "typeOf": ["period", "period of time", "time period"], "hasTypes": ["academic session", "academic term", "incumbency", "prison term", "school term", "sentence", "session", "tenure", "term of office", "time"]}, {"definition": "(usually plural) a statement of what is required as part of an agreement", "synonyms": ["condition", "strings"], "typeOf": ["statement"], "derivation": ["condition"], "usageOf": ["plural", "plural form"]}, {"definition": "any distinct quantity contained in a polynomial", "typeOf": ["quantity"]}, {"definition": "one of the substantive phrases in a logical proposition", "typeOf": ["constituent", "grammatical constituent"], "hasTypes": ["categorem", "categoreme", "major term", "middle term", "minor term", "predicate", "referent", "relatum", "subject"]}, {"definition": "the end of gestation or point at which birth is imminent", "synonyms": ["full term"], "typeOf": ["point", "point in time"]}, {"definition": "(architecture) a statue or a human bust or an animal carved out of the top of a square pillar; originally used as a boundary marker in ancient Rome", "synonyms": ["terminal figure", "terminus"], "typeOf": ["statue"], "inCategory": ["architecture"]}, {"definition": "name formally or designate with a term", "typeOf": ["be known as", "call", "know as", "name"], "derivation": ["term"]}]}
tests/events/look_wordsapi_response.json ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "word": "example",
3
+ "results": [
4
+ {
5
+ "definition": "a representative form or pattern",
6
+ "partOfSpeech": "noun",
7
+ "synonyms": [
8
+ "model"
9
+ ],
10
+ "typeOf": [
11
+ "representation",
12
+ "internal representation",
13
+ "mental representation"
14
+ ],
15
+ "hasTypes": [
16
+ "prefiguration",
17
+ "archetype",
18
+ "epitome",
19
+ "guide",
20
+ "holotype",
21
+ "image",
22
+ "loadstar",
23
+ "lodestar",
24
+ "microcosm",
25
+ "original",
26
+ "paradigm",
27
+ "pilot",
28
+ "prototype",
29
+ "template",
30
+ "templet",
31
+ "type specimen"
32
+ ],
33
+ "derivation": [
34
+ "exemplify"
35
+ ],
36
+ "examples": [
37
+ "I profited from his example"
38
+ ]
39
+ },
40
+ {
41
+ "definition": "something to be imitated",
42
+ "partOfSpeech": "noun",
43
+ "synonyms": [
44
+ "exemplar",
45
+ "good example",
46
+ "model"
47
+ ],
48
+ "typeOf": [
49
+ "ideal"
50
+ ],
51
+ "hasTypes": [
52
+ "pacemaker",
53
+ "pattern",
54
+ "beauty",
55
+ "prodigy",
56
+ "beaut",
57
+ "pacesetter"
58
+ ],
59
+ "derivation": [
60
+ "exemplify",
61
+ "exemplary"
62
+ ]
63
+ },
64
+ {
65
+ "definition": "an occurrence of something",
66
+ "partOfSpeech": "noun",
67
+ "synonyms": [
68
+ "case",
69
+ "instance"
70
+ ],
71
+ "typeOf": [
72
+ "happening",
73
+ "natural event",
74
+ "occurrence",
75
+ "occurrent"
76
+ ],
77
+ "hasTypes": [
78
+ "clip",
79
+ "mortification",
80
+ "piece",
81
+ "time",
82
+ "humiliation",
83
+ "bit"
84
+ ],
85
+ "derivation": [
86
+ "exemplify"
87
+ ],
88
+ "examples": [
89
+ "but there is always the famous example of the Smiths"
90
+ ]
91
+ },
92
+ {
93
+ "definition": "an item of information that is typical of a class or group",
94
+ "partOfSpeech": "noun",
95
+ "synonyms": [
96
+ "illustration",
97
+ "instance",
98
+ "representative"
99
+ ],
100
+ "typeOf": [
101
+ "information"
102
+ ],
103
+ "hasTypes": [
104
+ "excuse",
105
+ "apology",
106
+ "specimen",
107
+ "case in point",
108
+ "sample",
109
+ "exception",
110
+ "quintessence",
111
+ "precedent"
112
+ ],
113
+ "derivation": [
114
+ "exemplify",
115
+ "exemplary"
116
+ ],
117
+ "examples": [
118
+ "this patient provides a typical example of the syndrome",
119
+ "there is an example on page 10"
120
+ ]
121
+ },
122
+ {
123
+ "definition": "punishment intended as a warning to others",
124
+ "partOfSpeech": "noun",
125
+ "synonyms": [
126
+ "deterrent example",
127
+ "lesson",
128
+ "object lesson"
129
+ ],
130
+ "typeOf": [
131
+ "monition",
132
+ "admonition",
133
+ "word of advice",
134
+ "warning"
135
+ ],
136
+ "derivation": [
137
+ "exemplary"
138
+ ],
139
+ "examples": [
140
+ "they decided to make an example of him"
141
+ ]
142
+ },
143
+ {
144
+ "definition": "a task performed or problem solved in order to develop skill or understanding",
145
+ "partOfSpeech": "noun",
146
+ "synonyms": [
147
+ "exercise"
148
+ ],
149
+ "typeOf": [
150
+ "lesson"
151
+ ],
152
+ "examples": [
153
+ "you must work the examples at the end of each chapter in the textbook"
154
+ ]
155
+ }
156
+ ],
157
+ "syllables": {
158
+ "count": 3,
159
+ "list": [
160
+ "ex",
161
+ "am",
162
+ "ple"
163
+ ]
164
+ },
165
+ "pronunciation": {
166
+ "all": "ɪɡ'zæmpəl"
167
+ },
168
+ "frequency": 4.67
169
+ }
tests/events/thesaurus-wordnet.http ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @domain = http://localhost:7860
2
+
3
+ ### Thesaurus WordNet Query
4
+ POST {{domain}}/thesaurus-wordnet
5
+ Content-Type: text/plain;charset=UTF-8
6
+
7
+ {"query": "dog"}
8
+
9
+ > {%
10
+ client.log("Status:", response.status);
11
+ if (response.status >= 400) {
12
+ client.log("Error:", response.body);
13
+ } else {
14
+ client.log("Response:", response.body);
15
+ }
16
+ %}
tests/events/thesaurus-wordsapi.http ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @domain = http://localhost:7860
2
+
3
+ ### Thesaurus WordsAPI Query (with browser-like headers)
4
+ POST {{domain}}/thesaurus-wordsapi
5
+ Content-Type: text/plain;charset=UTF-8
6
+
7
+ {"query":"look"}
8
+
9
+ > {%
10
+ client.log("Status:", response.status);
11
+ if (response.status >= 400) {
12
+ client.log("Error:", response.body);
13
+ } else {
14
+ client.log("Response:", response.body);
15
+ }
16
+ %}
tests/test_thesaurus_wordnet.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import unittest
3
+
4
+ from tests import EVENTS_FOLDER
5
+
6
+
7
+ def assert_get_synsets_by_word_and_language(cls, q):
8
+ from my_ghost_writer.thesaurus import get_synsets_by_word_and_language
9
+
10
+ response = get_synsets_by_word_and_language(q, lang="eng")
11
+ cls.assertEqual(list(response.keys()), ['word', 'results'])
12
+ cls.assertEqual(response["word"], q)
13
+ cls.assertIsInstance(response["results"], list)
14
+ results = response["results"]
15
+ for result in results:
16
+ for k, v in result.items():
17
+ cls.assertIsInstance(k, str)
18
+ try:
19
+ if k == "definition":
20
+ cls.assertIsInstance(v, str)
21
+ else:
22
+ cls.assertIsInstance(v, list)
23
+ except AssertionError as ae:
24
+ print(k, v, ae)
25
+ for s in v:
26
+ cls.assertIsInstance(s, str)
27
+ with open(EVENTS_FOLDER / f"expected_get_synsets_by_word_and_language_{q}.json", "r") as src:
28
+ # json.dump(response, src)
29
+ expected_response = json.load(src)
30
+ cls.assertEqual(response, expected_response)
31
+
32
+
33
+ class TestThesaurusWordnet(unittest.TestCase):
34
+ def test_get_current_info_wordnet(self):
35
+ from my_ghost_writer.thesaurus import get_current_info_wordnet
36
+
37
+ current_info = get_current_info_wordnet()
38
+ self.assertEqual(list(current_info.keys()), ['languages', 'version'])
39
+ languages = current_info["languages"]
40
+ self.assertIn("eng", languages)
41
+ self.assertIsInstance(languages, list)
42
+ self.assertIsInstance(current_info["version"], str)
43
+ self.assertGreaterEqual(len(languages), 1)
44
+
45
+ def test_get_synsets_by_word_and_language(self):
46
+ assert_get_synsets_by_word_and_language(self, "dog")
47
+ assert_get_synsets_by_word_and_language(self, "look")
48
+ assert_get_synsets_by_word_and_language(self, "power")
49
+ assert_get_synsets_by_word_and_language(self, "term")