-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfix_pxus.py
148 lines (122 loc) · 4.06 KB
/
fix_pxus.py
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
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/usr/bin/env python3
import os
import sys
from dataclasses import dataclass
from pprint import pprint
from openai import OpenAI
@dataclass
class PxuRecord:
path: str
location: tuple[int, int]
text: str
replacement: str = ""
def find_pxu_files(path):
"""
A generator that yield all the .pxu files in the given path (recurssively)
"""
for root, dirs, files in os.walk(path):
for file in files:
if file.endswith(".pxu"):
yield os.path.join(root, file)
def find_records_in_pxu(path):
"""
A generator that yield all the records in the given .pxu file.
The records are blocks of text separated by one or more empty lines.
"""
with open(path, "r") as f:
record = ""
start_line = 0
end_line = 0
for line_no, line in enumerate(f):
if line.strip():
if not record:
start_line = line_no
record += line
elif record:
end_line = line_no - 1
yield PxuRecord(path, (start_line, end_line), record)
record = ""
if record:
end_line = line_no
yield PxuRecord(path, (start_line, end_line), record)
def record_to_dict(record):
"""
Convert a record to a dictionary.
If the line of a record starts with a letter,
then the word before the colon is the field name.
if it starts with a whitespace then its a continuation of the previous field.
"""
result = {}
field = None
for line in record:
if line[0].isalpha() or line[0] == "_":
try:
field, value = line.split(":", 1)
result[field] = value.strip()
except ValueError:
print("Error: ", line)
elif field:
result[field] += "\n" + line
return result
class PxuFixer:
def __init__(self):
OPENAI_KEY = os.environ.get("OPENAI_KEY")
if not OPENAI_KEY:
raise SystemExit("OPENAI_KEY environment variable is not set.")
self._client = OpenAI(api_key=OPENAI_KEY)
self._sys_prompt = open('system_prompt.txt', 'r').read()
self._model = "gpt-4-turbo-preview"
# self._model = "gpt-3.5-turbo-0125"
def process_pxu(self, pxu_text):
messages = [
{
"role": "system",
"content": self._sys_prompt
},
{
"role": "user",
"content": pxu_text
}
]
completion = self._client.chat.completions.create(
model=self._model,
messages = messages,
)
return completion.choices[0].message.content.strip()
def main():
if len(sys.argv) != 2:
raise SystemExit("Usage: fix_pxus.py <path>")
# find all the pxu files
pxu_files = list(find_pxu_files(sys.argv[1]))
pxu_fixer = PxuFixer()
for pxu_file in pxu_files:
# skip files that (should) not have jobs in them
skipped_files = [
"testplan.pxu",
"test-plan.pxu",
"resource.pxu",
"packaging.pxu",
"manifest.pxu",
"category.pxu",]
if os.path.basename(pxu_file) in skipped_files:
continue
recs = list(find_records_in_pxu(pxu_file))
for record in recs:
print(record.path, record.location)
#print(record.text)
res = pxu_fixer.process_pxu(record.text)
if "===NO CHANGE===" in res:
record.replacement = record.text
else:
record.replacement = res
# ensure that the records are properly terminated
if record.replacement[-1] != "\n":
record.replacement += "\n"
print(res)
# replace the contents of the file with the new contents
with open(pxu_file, "w") as f:
f.write(
"\n".join(rec.replacement for rec in recs)
)
if __name__ == "__main__":
main()