-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathanalysis.py
More file actions
135 lines (110 loc) · 3.58 KB
/
analysis.py
File metadata and controls
135 lines (110 loc) · 3.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import hashlib
import json
import os
from http import HTTPStatus
from pathlib import Path
from typing import override, Any
import requests
from pydantic import BaseModel
from PyQt6.QtCore import QThread, pyqtSignal
from config import Config
class TextSpan(BaseModel):
content: str
# beginOffset: int
class PartOfSpeech(BaseModel):
tag: str
# aspect: str
# case: str
# form: str
# gender: str
# mood: str
# number: str
# person: str
# proper: str
# reciprocity: str
# tense: str
# voice: str
# class Sentence(BaseModel):
# text: TextSpan
# class DependencyEdge(BaseModel):
# headTokenIndex: int
# label: str
class Token(BaseModel):
text: TextSpan
partOfSpeech: PartOfSpeech
# dependencyEdge: DependencyEdge
lemma: str
class SyntaxAnalysis(BaseModel):
# sentences: list[Sentence]
tokens: list[Token]
language: str
class AnalysisWorker(QThread):
finished = pyqtSignal(SyntaxAnalysis)
error = pyqtSignal(str)
def __init__(self, content: str, game_language: str, config: Config) -> None:
super().__init__()
self._content = content
self._game_language = game_language
self._config = config
self._interrupted = False
@override
def run(self) -> None:
try:
result = _get_analysis(
self._content, self._game_language, self._config.google_api_key
)
if (
os.environ.get("GT_DEV") == "true"
and (delay := int(os.environ.get("GT_ANALYSIS_DELAY", 0))) > 0
):
import time
time.sleep(delay)
if not self._interrupted:
self.finished.emit(result)
except Exception as e:
if not self._interrupted:
self.error.emit(str(e))
def interrupt(self) -> None:
self._interrupted = True
def _get_analysis(
content: str, game_language: str, google_api_key: str
) -> SyntaxAnalysis:
document = {
"document": {
"content": content,
"language": game_language,
"type": "PLAIN_TEXT",
},
"encodingType": "UTF8",
}
document_str = json.dumps(document)
if os.environ.get("GT_DEV") == "true":
hash_bytes = hashlib.sha256(document_str.encode()).digest()
hash_hex = hash_bytes.hex()
cache_path = Path(f"dev/analysis_cache/{hash_hex}.json")
if not cache_path.exists():
response_json = _request_analysis(document_str, google_api_key)
cache_path.parent.mkdir(parents=True, exist_ok=True)
with open(cache_path, "w", encoding="utf-8") as f:
json.dump(response_json, f, ensure_ascii=False, indent=4)
return SyntaxAnalysis.model_validate(response_json)
else:
with open(cache_path, "r", encoding="utf-8") as f:
return SyntaxAnalysis.model_validate_json(f.read())
else:
response_json = _request_analysis(document_str, google_api_key)
return SyntaxAnalysis.model_validate(response_json)
def _request_analysis(document_str: str, google_api_key: str) -> dict[str, Any]:
response = requests.post(
"https://language.googleapis.com/v1/documents:analyzeSyntax",
data=document_str,
headers={
"Content-Type": "application/json",
"X-goog-api-key": google_api_key,
},
)
response_json = response.json()
if response.status_code != HTTPStatus.OK.value:
raise Exception(str(response_json))
else:
return response_json