langroid 0.16.7__py3-none-any.whl → 0.17.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- langroid/agent/base.py +45 -21
- langroid/agent/chat_agent.py +22 -14
- langroid/agent/chat_document.py +22 -13
- langroid/agent/tool_message.py +11 -11
- langroid/agent/tools/file_tools.py +234 -0
- langroid/agent/xml_tool_message.py +178 -45
- langroid/utils/constants.py +2 -0
- langroid/utils/git_utils.py +251 -0
- langroid/utils/system.py +78 -0
- {langroid-0.16.7.dist-info → langroid-0.17.0.dist-info}/METADATA +6 -3
- {langroid-0.16.7.dist-info → langroid-0.17.0.dist-info}/RECORD +14 -89
- pyproject.toml +3 -2
- langroid/agent/md_tool_message_grammar.py +0 -455
- langroid/agent/tools/code_file_tool_parse.py +0 -150
- langroid/agent/tools/code_file_tool_pyparsing.py +0 -194
- langroid/agent/tools/code_file_tool_pyparsing2.py +0 -199
- langroid/agent/tools/extract_tool.py +0 -96
- langroid/agent/tools/formatted_model_custom.py +0 -150
- langroid/agent/tools/formatted_model_custom2.py +0 -168
- langroid/agent/tools/formatted_model_custom3.py +0 -279
- langroid/agent/tools/formatted_model_custom4.py +0 -395
- langroid/agent/tools/formatted_model_jinja.py +0 -133
- langroid/agent/tools/formatted_model_jinja.py-e +0 -122
- langroid/agent/tools/formatted_model_jinja2.py +0 -145
- langroid/agent/tools/formatted_model_jinja2.py-e +0 -135
- langroid/agent/tools/formatted_model_lark.py +0 -0
- langroid/agent/tools/formatted_model_lark2.py +0 -168
- langroid/agent/tools/formatted_model_parse.py +0 -105
- langroid/agent/tools/formatted_model_parse.py-e +0 -98
- langroid/agent/tools/formatted_model_parse2.py +0 -113
- langroid/agent/tools/formatted_model_parse2.py-e +0 -109
- langroid/agent/tools/formatted_model_parse3.py +0 -114
- langroid/agent/tools/formatted_model_parse3.py-e +0 -110
- langroid/agent/tools/formatted_model_parsimon.py +0 -194
- langroid/agent/tools/formatted_model_parsimon.py-e +0 -186
- langroid/agent/tools/formatted_model_pyparsing.py +0 -169
- langroid/agent/tools/formatted_model_pyparsing.py-e +0 -149
- langroid/agent/tools/formatted_model_pyparsing2.py +0 -159
- langroid/agent/tools/formatted_model_pyparsing2.py-e +0 -143
- langroid/agent/tools/formatted_model_pyparsing3.py +0 -133
- langroid/agent/tools/formatted_model_pyparsing3.py-e +0 -121
- langroid/agent/tools/formatted_model_pyparsing4.py +0 -213
- langroid/agent/tools/formatted_model_pyparsing4.py-e +0 -176
- langroid/agent/tools/formatted_model_pyparsing5.py +0 -173
- langroid/agent/tools/formatted_model_pyparsing5.py-e +0 -142
- langroid/agent/tools/formatted_model_regex.py +0 -246
- langroid/agent/tools/formatted_model_regex.py-e +0 -248
- langroid/agent/tools/formatted_model_regex2.py +0 -250
- langroid/agent/tools/formatted_model_regex2.py-e +0 -253
- langroid/agent/tools/formatted_model_tatsu.py +0 -172
- langroid/agent/tools/formatted_model_tatsu.py-e +0 -160
- langroid/agent/tools/formatted_model_template.py +0 -217
- langroid/agent/tools/formatted_model_template.py-e +0 -200
- langroid/agent/tools/formatted_model_xml.py +0 -178
- langroid/agent/tools/formatted_model_xml2.py +0 -178
- langroid/agent/tools/formatted_model_xml3.py +0 -132
- langroid/agent/tools/formatted_model_xml4.py +0 -130
- langroid/agent/tools/formatted_model_xml5.py +0 -130
- langroid/agent/tools/formatted_model_xml6.py +0 -113
- langroid/agent/tools/formatted_model_xml7.py +0 -117
- langroid/agent/tools/formatted_model_xml8.py +0 -164
- langroid/agent/tools/generator_tool.py +0 -20
- langroid/agent/tools/generic_tool.py +0 -165
- langroid/agent/tools/generic_tool_tatsu.py +0 -275
- langroid/agent/tools/grammar_based_model.py +0 -132
- langroid/agent/tools/grammar_based_model.py-e +0 -128
- langroid/agent/tools/grammar_based_model_lark.py +0 -156
- langroid/agent/tools/grammar_based_model_lark.py-e +0 -153
- langroid/agent/tools/grammar_based_model_parse.py +0 -86
- langroid/agent/tools/grammar_based_model_parse.py-e +0 -80
- langroid/agent/tools/grammar_based_model_parsimonious.py +0 -129
- langroid/agent/tools/grammar_based_model_parsimonious.py-e +0 -120
- langroid/agent/tools/grammar_based_model_pyparsing.py +0 -105
- langroid/agent/tools/grammar_based_model_pyparsing.py-e +0 -103
- langroid/agent/tools/grammar_based_model_regex.py +0 -139
- langroid/agent/tools/grammar_based_model_regex.py-e +0 -130
- langroid/agent/tools/grammar_based_model_regex2.py +0 -124
- langroid/agent/tools/grammar_based_model_regex2.py-e +0 -116
- langroid/agent/tools/grammar_based_model_tatsu.py +0 -80
- langroid/agent/tools/grammar_based_model_tatsu.py-e +0 -77
- langroid/agent/tools/lark_earley_example.py +0 -135
- langroid/agent/tools/lark_earley_example.py-e +0 -117
- langroid/agent/tools/lark_example.py +0 -72
- langroid/agent/tools/note_tool.py +0 -0
- langroid/agent/tools/parse_example.py +0 -76
- langroid/agent/tools/parse_example2.py +0 -87
- langroid/agent/tools/parse_example3.py +0 -42
- langroid/agent/tools/parse_test.py +0 -791
- langroid/agent/tools/run_python_code.py +0 -60
- {langroid-0.16.7.dist-info → langroid-0.17.0.dist-info}/LICENSE +0 -0
- {langroid-0.16.7.dist-info → langroid-0.17.0.dist-info}/WHEEL +0 -0
@@ -1,113 +0,0 @@
|
|
1
|
-
from abc import ABC, abstractmethod
|
2
|
-
from typing import ClassVar, Dict
|
3
|
-
|
4
|
-
import parse
|
5
|
-
|
6
|
-
from langroid.pydantic_v1 import BaseModel
|
7
|
-
|
8
|
-
|
9
|
-
class FormattingModel(BaseModel, ABC):
|
10
|
-
start_token: ClassVar[str] = "<format>"
|
11
|
-
end_token: ClassVar[str] = "</format>"
|
12
|
-
field_token_map: ClassVar[Dict[str, str]] = {}
|
13
|
-
|
14
|
-
@classmethod
|
15
|
-
@abstractmethod
|
16
|
-
def format_spec(cls) -> str:
|
17
|
-
pass
|
18
|
-
|
19
|
-
@classmethod
|
20
|
-
@abstractmethod
|
21
|
-
def parse_spec(cls) -> str:
|
22
|
-
pass
|
23
|
-
|
24
|
-
@classmethod
|
25
|
-
def parse(cls, formatted_string: str) -> "FormattingModel":
|
26
|
-
parser = parse.compile(cls.parse_spec())
|
27
|
-
result = parser.parse(formatted_string)
|
28
|
-
if result is None:
|
29
|
-
raise ValueError(f"Unable to parse: {formatted_string}")
|
30
|
-
return cls(**result.named)
|
31
|
-
|
32
|
-
def format(self) -> str:
|
33
|
-
format_string = self.format_spec()
|
34
|
-
field_values = {k: getattr(self, k) for k in self.__annotations__}
|
35
|
-
return format_string.format(**field_values)
|
36
|
-
|
37
|
-
|
38
|
-
class CodeFileModel(FormattingModel):
|
39
|
-
language: str
|
40
|
-
file_path: str
|
41
|
-
code: str
|
42
|
-
|
43
|
-
start_token: ClassVar[str] = "<format>"
|
44
|
-
end_token: ClassVar[str] = "</format>"
|
45
|
-
|
46
|
-
@classmethod
|
47
|
-
def format_spec(cls) -> str:
|
48
|
-
return (
|
49
|
-
f"{cls.start_token}\n"
|
50
|
-
"code_file_model\n"
|
51
|
-
"{file_path}\n"
|
52
|
-
"```{language}\n"
|
53
|
-
"{code}\n"
|
54
|
-
"```\n"
|
55
|
-
f"{cls.end_token}"
|
56
|
-
)
|
57
|
-
|
58
|
-
@classmethod
|
59
|
-
def parse_spec(cls) -> str:
|
60
|
-
return (
|
61
|
-
f"{cls.start_token}\n"
|
62
|
-
"code_file_model\n"
|
63
|
-
"{file_path}\n"
|
64
|
-
"```{language}\n"
|
65
|
-
"{code}\n"
|
66
|
-
"```\n"
|
67
|
-
f"{cls.end_token}"
|
68
|
-
)
|
69
|
-
|
70
|
-
|
71
|
-
# Informal tests
|
72
|
-
if __name__ == "__main__":
|
73
|
-
# Test CodeFileModel
|
74
|
-
my_model = CodeFileModel(
|
75
|
-
language="python",
|
76
|
-
file_path="src/main.py",
|
77
|
-
code='def hello():\n print("hello world")',
|
78
|
-
)
|
79
|
-
|
80
|
-
formatted = my_model.format()
|
81
|
-
print("Formatted:")
|
82
|
-
print(formatted)
|
83
|
-
|
84
|
-
parsed = CodeFileModel.parse(formatted)
|
85
|
-
print("\nParsed:")
|
86
|
-
print(parsed)
|
87
|
-
|
88
|
-
assert my_model == parsed, "Round trip failed"
|
89
|
-
|
90
|
-
# Test more lenient parsing
|
91
|
-
lenient_formatted = """<format>
|
92
|
-
code_file_model
|
93
|
-
src/test.py
|
94
|
-
```javascript
|
95
|
-
function test() {
|
96
|
-
console.log("Hello, world!");
|
97
|
-
}
|
98
|
-
```
|
99
|
-
</format>"""
|
100
|
-
|
101
|
-
parsed_lenient = CodeFileModel.parse(lenient_formatted)
|
102
|
-
print("\nParsed lenient:")
|
103
|
-
print(parsed_lenient)
|
104
|
-
|
105
|
-
# Test invalid format
|
106
|
-
try:
|
107
|
-
CodeFileModel.parse("Invalid format")
|
108
|
-
except ValueError as e:
|
109
|
-
print(f"\nCaught expected ValueError: {e}")
|
110
|
-
else:
|
111
|
-
assert False, "Expected ValueError was not raised"
|
112
|
-
|
113
|
-
print("\nAll tests passed!")
|
@@ -1,109 +0,0 @@
|
|
1
|
-
from abc import ABC, abstractmethod
|
2
|
-
from typing import Dict, ClassVar
|
3
|
-
from pydantic import BaseModel
|
4
|
-
import parse
|
5
|
-
|
6
|
-
class FormattingModel(BaseModel, ABC):
|
7
|
-
start_token: ClassVar[str] = "<format>"
|
8
|
-
end_token: ClassVar[str] = "</format>"
|
9
|
-
field_token_map: ClassVar[Dict[str, str]] = {}
|
10
|
-
|
11
|
-
@classmethod
|
12
|
-
@abstractmethod
|
13
|
-
def format_spec(cls) -> str:
|
14
|
-
pass
|
15
|
-
|
16
|
-
@classmethod
|
17
|
-
@abstractmethod
|
18
|
-
def parse_spec(cls) -> str:
|
19
|
-
pass
|
20
|
-
|
21
|
-
@classmethod
|
22
|
-
def parse(cls, formatted_string: str) -> 'FormattingModel':
|
23
|
-
parser = parse.compile(cls.parse_spec())
|
24
|
-
result = parser.parse(formatted_string)
|
25
|
-
if result is None:
|
26
|
-
raise ValueError(f"Unable to parse: {formatted_string}")
|
27
|
-
return cls(**result.named)
|
28
|
-
|
29
|
-
def format(self) -> str:
|
30
|
-
format_string = self.format_spec()
|
31
|
-
field_values = {k: getattr(self, k) for k in self.__annotations__}
|
32
|
-
return format_string.format(**field_values)
|
33
|
-
|
34
|
-
class CodeFileModel(FormattingModel):
|
35
|
-
language: str
|
36
|
-
file_path: str
|
37
|
-
code: str
|
38
|
-
|
39
|
-
start_token: ClassVar[str] = "<format>"
|
40
|
-
end_token: ClassVar[str] = "</format>"
|
41
|
-
|
42
|
-
@classmethod
|
43
|
-
def format_spec(cls) -> str:
|
44
|
-
return (
|
45
|
-
f"{cls.start_token}\n"
|
46
|
-
"code_file_model\n"
|
47
|
-
"{file_path}\n"
|
48
|
-
"```{language}\n"
|
49
|
-
"{code}\n"
|
50
|
-
"```\n"
|
51
|
-
f"{cls.end_token}"
|
52
|
-
)
|
53
|
-
|
54
|
-
@classmethod
|
55
|
-
def parse_spec(cls) -> str:
|
56
|
-
return (
|
57
|
-
f"{cls.start_token}\n"
|
58
|
-
"code_file_model\n"
|
59
|
-
"{file_path}\n"
|
60
|
-
"```{language}\n"
|
61
|
-
"{code}\n"
|
62
|
-
"```\n"
|
63
|
-
f"{cls.end_token}"
|
64
|
-
)
|
65
|
-
|
66
|
-
# Informal tests
|
67
|
-
if __name__ == "__main__":
|
68
|
-
# Test CodeFileModel
|
69
|
-
my_model = CodeFileModel(
|
70
|
-
language="python",
|
71
|
-
file_path="src/main.py",
|
72
|
-
code="def hello():\n print(\"hello world\")"
|
73
|
-
)
|
74
|
-
|
75
|
-
formatted = my_model.format()
|
76
|
-
print("Formatted:")
|
77
|
-
print(formatted)
|
78
|
-
|
79
|
-
parsed = CodeFileModel.parse(formatted)
|
80
|
-
print("\nParsed:")
|
81
|
-
print(parsed)
|
82
|
-
|
83
|
-
assert my_model == parsed, "Round trip failed"
|
84
|
-
|
85
|
-
# Test more lenient parsing
|
86
|
-
lenient_formatted = """<format>
|
87
|
-
code_file_model
|
88
|
-
src/test.py
|
89
|
-
```javascript
|
90
|
-
function test() {
|
91
|
-
console.log("Hello, world!");
|
92
|
-
}
|
93
|
-
```
|
94
|
-
</format>"""
|
95
|
-
|
96
|
-
parsed_lenient = CodeFileModel.parse(lenient_formatted)
|
97
|
-
print("\nParsed lenient:")
|
98
|
-
print(parsed_lenient)
|
99
|
-
|
100
|
-
# Test invalid format
|
101
|
-
try:
|
102
|
-
CodeFileModel.parse("Invalid format")
|
103
|
-
except ValueError as e:
|
104
|
-
print(f"\nCaught expected ValueError: {e}")
|
105
|
-
else:
|
106
|
-
assert False, "Expected ValueError was not raised"
|
107
|
-
|
108
|
-
print("\nAll tests passed!")
|
109
|
-
|
@@ -1,114 +0,0 @@
|
|
1
|
-
from abc import ABC, abstractmethod
|
2
|
-
from typing import ClassVar, Dict
|
3
|
-
|
4
|
-
import parse
|
5
|
-
|
6
|
-
from langroid.pydantic_v1 import BaseModel
|
7
|
-
|
8
|
-
|
9
|
-
class FormattingModel(BaseModel, ABC):
|
10
|
-
start_token: ClassVar[str] = "<format>"
|
11
|
-
end_token: ClassVar[str] = "</format>"
|
12
|
-
field_token_map: ClassVar[Dict[str, str]] = {}
|
13
|
-
|
14
|
-
@classmethod
|
15
|
-
@abstractmethod
|
16
|
-
def format_spec(cls) -> str:
|
17
|
-
pass
|
18
|
-
|
19
|
-
@classmethod
|
20
|
-
@abstractmethod
|
21
|
-
def parse_spec(cls) -> str:
|
22
|
-
pass
|
23
|
-
|
24
|
-
@classmethod
|
25
|
-
def parse(cls, formatted_string: str) -> "FormattingModel":
|
26
|
-
parser = parse.compile(cls.parse_spec())
|
27
|
-
result = parser.parse(formatted_string)
|
28
|
-
if result is None:
|
29
|
-
raise ValueError(f"Unable to parse: {formatted_string}")
|
30
|
-
return cls(**result.named)
|
31
|
-
|
32
|
-
def format(self) -> str:
|
33
|
-
format_string = self.format_spec()
|
34
|
-
field_values = {k: getattr(self, k) for k in self.__annotations__}
|
35
|
-
return format_string.format(**field_values)
|
36
|
-
|
37
|
-
|
38
|
-
class CodeFileModel(FormattingModel):
|
39
|
-
language: str
|
40
|
-
file_path: str
|
41
|
-
code: str
|
42
|
-
|
43
|
-
start_token: ClassVar[str] = "<format>"
|
44
|
-
end_token: ClassVar[str] = "</format>"
|
45
|
-
|
46
|
-
@classmethod
|
47
|
-
def format_spec(cls) -> str:
|
48
|
-
return (
|
49
|
-
f"{cls.start_token}\n"
|
50
|
-
"code_file_model\n"
|
51
|
-
"{file_path}\n"
|
52
|
-
"```{language}\n"
|
53
|
-
"{code}\n"
|
54
|
-
"```\n"
|
55
|
-
f"{cls.end_token}"
|
56
|
-
)
|
57
|
-
|
58
|
-
@classmethod
|
59
|
-
def parse_spec(cls) -> str:
|
60
|
-
return (
|
61
|
-
f"{cls.start_token}\n"
|
62
|
-
"code_file_model\n"
|
63
|
-
"{file_path:^}\n"
|
64
|
-
"```{language:^}\n"
|
65
|
-
"{code}\n"
|
66
|
-
"```\n"
|
67
|
-
f"{cls.end_token}"
|
68
|
-
)
|
69
|
-
|
70
|
-
|
71
|
-
# Informal tests
|
72
|
-
if __name__ == "__main__":
|
73
|
-
# Test CodeFileModel
|
74
|
-
my_model = CodeFileModel(
|
75
|
-
language="python",
|
76
|
-
file_path="src/main.py",
|
77
|
-
code='def hello():\n print("hello world")',
|
78
|
-
)
|
79
|
-
|
80
|
-
formatted = my_model.format()
|
81
|
-
print("Formatted:")
|
82
|
-
print(formatted)
|
83
|
-
|
84
|
-
parsed = CodeFileModel.parse(formatted)
|
85
|
-
print("\nParsed:")
|
86
|
-
print(parsed)
|
87
|
-
|
88
|
-
assert my_model == parsed, "Round trip failed"
|
89
|
-
|
90
|
-
# Test more lenient parsing
|
91
|
-
lenient_formatted = """<format>
|
92
|
-
code_file_model
|
93
|
-
src/test.py
|
94
|
-
|
95
|
-
``` javascript
|
96
|
-
function test() {
|
97
|
-
console.log("Hello, world!");
|
98
|
-
}
|
99
|
-
```
|
100
|
-
</format>"""
|
101
|
-
|
102
|
-
parsed_lenient = CodeFileModel.parse(lenient_formatted)
|
103
|
-
print("\nParsed lenient:")
|
104
|
-
print(parsed_lenient)
|
105
|
-
|
106
|
-
# Test invalid format
|
107
|
-
try:
|
108
|
-
CodeFileModel.parse("Invalid format")
|
109
|
-
except ValueError as e:
|
110
|
-
print(f"\nCaught expected ValueError: {e}")
|
111
|
-
else:
|
112
|
-
assert False, "Expected ValueError was not raised"
|
113
|
-
|
114
|
-
print("\nAll tests passed!")
|
@@ -1,110 +0,0 @@
|
|
1
|
-
from abc import ABC, abstractmethod
|
2
|
-
from typing import Dict, ClassVar
|
3
|
-
from pydantic import BaseModel
|
4
|
-
import parse
|
5
|
-
|
6
|
-
class FormattingModel(BaseModel, ABC):
|
7
|
-
start_token: ClassVar[str] = "<format>"
|
8
|
-
end_token: ClassVar[str] = "</format>"
|
9
|
-
field_token_map: ClassVar[Dict[str, str]] = {}
|
10
|
-
|
11
|
-
@classmethod
|
12
|
-
@abstractmethod
|
13
|
-
def format_spec(cls) -> str:
|
14
|
-
pass
|
15
|
-
|
16
|
-
@classmethod
|
17
|
-
@abstractmethod
|
18
|
-
def parse_spec(cls) -> str:
|
19
|
-
pass
|
20
|
-
|
21
|
-
@classmethod
|
22
|
-
def parse(cls, formatted_string: str) -> 'FormattingModel':
|
23
|
-
parser = parse.compile(cls.parse_spec())
|
24
|
-
result = parser.parse(formatted_string)
|
25
|
-
if result is None:
|
26
|
-
raise ValueError(f"Unable to parse: {formatted_string}")
|
27
|
-
return cls(**result.named)
|
28
|
-
|
29
|
-
def format(self) -> str:
|
30
|
-
format_string = self.format_spec()
|
31
|
-
field_values = {k: getattr(self, k) for k in self.__annotations__}
|
32
|
-
return format_string.format(**field_values)
|
33
|
-
|
34
|
-
class CodeFileModel(FormattingModel):
|
35
|
-
language: str
|
36
|
-
file_path: str
|
37
|
-
code: str
|
38
|
-
|
39
|
-
start_token: ClassVar[str] = "<format>"
|
40
|
-
end_token: ClassVar[str] = "</format>"
|
41
|
-
|
42
|
-
@classmethod
|
43
|
-
def format_spec(cls) -> str:
|
44
|
-
return (
|
45
|
-
f"{cls.start_token}\n"
|
46
|
-
"code_file_model\n"
|
47
|
-
"{file_path}\n"
|
48
|
-
"```{language}\n"
|
49
|
-
"{code}\n"
|
50
|
-
"```\n"
|
51
|
-
f"{cls.end_token}"
|
52
|
-
)
|
53
|
-
|
54
|
-
@classmethod
|
55
|
-
def parse_spec(cls) -> str:
|
56
|
-
return (
|
57
|
-
f"{cls.start_token}\n"
|
58
|
-
"code_file_model\n"
|
59
|
-
"{file_path:^}\n"
|
60
|
-
"```{language:^}\n"
|
61
|
-
"{code}\n"
|
62
|
-
"```\n"
|
63
|
-
f"{cls.end_token}"
|
64
|
-
)
|
65
|
-
|
66
|
-
# Informal tests
|
67
|
-
if __name__ == "__main__":
|
68
|
-
# Test CodeFileModel
|
69
|
-
my_model = CodeFileModel(
|
70
|
-
language="python",
|
71
|
-
file_path="src/main.py",
|
72
|
-
code="def hello():\n print(\"hello world\")"
|
73
|
-
)
|
74
|
-
|
75
|
-
formatted = my_model.format()
|
76
|
-
print("Formatted:")
|
77
|
-
print(formatted)
|
78
|
-
|
79
|
-
parsed = CodeFileModel.parse(formatted)
|
80
|
-
print("\nParsed:")
|
81
|
-
print(parsed)
|
82
|
-
|
83
|
-
assert my_model == parsed, "Round trip failed"
|
84
|
-
|
85
|
-
# Test more lenient parsing
|
86
|
-
lenient_formatted = """<format>
|
87
|
-
code_file_model
|
88
|
-
src/test.py
|
89
|
-
|
90
|
-
``` javascript
|
91
|
-
function test() {
|
92
|
-
console.log("Hello, world!");
|
93
|
-
}
|
94
|
-
```
|
95
|
-
</format>"""
|
96
|
-
|
97
|
-
parsed_lenient = CodeFileModel.parse(lenient_formatted)
|
98
|
-
print("\nParsed lenient:")
|
99
|
-
print(parsed_lenient)
|
100
|
-
|
101
|
-
# Test invalid format
|
102
|
-
try:
|
103
|
-
CodeFileModel.parse("Invalid format")
|
104
|
-
except ValueError as e:
|
105
|
-
print(f"\nCaught expected ValueError: {e}")
|
106
|
-
else:
|
107
|
-
assert False, "Expected ValueError was not raised"
|
108
|
-
|
109
|
-
print("\nAll tests passed!")
|
110
|
-
|
@@ -1,194 +0,0 @@
|
|
1
|
-
from abc import ABC, abstractmethod
|
2
|
-
|
3
|
-
from parsimonious import Grammar, NodeVisitor, exceptions
|
4
|
-
|
5
|
-
from langroid.pydantic_v1 import BaseModel
|
6
|
-
|
7
|
-
|
8
|
-
class FormattingModel(BaseModel, ABC):
|
9
|
-
@classmethod
|
10
|
-
@abstractmethod
|
11
|
-
def format_spec(cls):
|
12
|
-
pass
|
13
|
-
|
14
|
-
@classmethod
|
15
|
-
@abstractmethod
|
16
|
-
def parse_spec(cls):
|
17
|
-
pass
|
18
|
-
|
19
|
-
@classmethod
|
20
|
-
@abstractmethod
|
21
|
-
def parse_visitor(cls):
|
22
|
-
pass
|
23
|
-
|
24
|
-
@classmethod
|
25
|
-
@abstractmethod
|
26
|
-
def start_token(cls) -> str:
|
27
|
-
pass
|
28
|
-
|
29
|
-
@classmethod
|
30
|
-
@abstractmethod
|
31
|
-
def end_token(cls) -> str:
|
32
|
-
pass
|
33
|
-
|
34
|
-
@classmethod
|
35
|
-
def format(cls, instance: "FormattingModel") -> str:
|
36
|
-
spec = cls.format_spec()
|
37
|
-
formatted = spec.format(**instance.dict())
|
38
|
-
return f"{cls.start_token()}\n{formatted}\n{cls.end_token()}"
|
39
|
-
|
40
|
-
@classmethod
|
41
|
-
def parse(cls, formatted_string: str) -> "FormattingModel":
|
42
|
-
lines = formatted_string.strip().split("\n")
|
43
|
-
if lines[0] != cls.start_token() or lines[-1] != cls.end_token():
|
44
|
-
raise ValueError("Invalid start or end token")
|
45
|
-
content = "\n".join(lines[1:-1])
|
46
|
-
|
47
|
-
grammar = Grammar(cls.parse_spec())
|
48
|
-
try:
|
49
|
-
tree = grammar.parse(content)
|
50
|
-
except exceptions.ParseError as e:
|
51
|
-
raise ValueError(f"Failed to parse content: {e}\nContent:\n{content}")
|
52
|
-
|
53
|
-
visitor = cls.parse_visitor()()
|
54
|
-
try:
|
55
|
-
visitor_result = visitor.visit(tree)
|
56
|
-
except Exception as e:
|
57
|
-
raise ValueError(f"Error during tree visitation: {e}")
|
58
|
-
|
59
|
-
if not all(field in visitor_result for field in cls.__fields__):
|
60
|
-
missing_fields = [
|
61
|
-
field for field in cls.__fields__ if field not in visitor_result
|
62
|
-
]
|
63
|
-
raise ValueError(
|
64
|
-
f"Missing fields after parsing: {', '.join(missing_fields)}"
|
65
|
-
)
|
66
|
-
|
67
|
-
return cls(**visitor_result)
|
68
|
-
|
69
|
-
|
70
|
-
class CodeFileModel(FormattingModel):
|
71
|
-
language: str
|
72
|
-
file_path: str
|
73
|
-
code: str
|
74
|
-
|
75
|
-
@classmethod
|
76
|
-
def format_spec(cls):
|
77
|
-
return "code_file_model\n{file_path}\n```{language}\n{code}\n```"
|
78
|
-
|
79
|
-
@classmethod
|
80
|
-
def parse_spec(cls):
|
81
|
-
return """
|
82
|
-
model = "code_file_model" newline file_path newline code_block
|
83
|
-
file_path = line
|
84
|
-
code_block = "```" language newline code "```"
|
85
|
-
language = ~"[^\\n]+"
|
86
|
-
code = (!(~"```") (newline / any_char))*
|
87
|
-
line = ~"[^\\n]+"
|
88
|
-
newline = ~"\\s*\\n\\s*"
|
89
|
-
any_char = ~"."
|
90
|
-
"""
|
91
|
-
|
92
|
-
@classmethod
|
93
|
-
def parse_visitor(cls):
|
94
|
-
class Visitor(NodeVisitor):
|
95
|
-
def __init__(self):
|
96
|
-
self.data = {}
|
97
|
-
|
98
|
-
def visit_model(self, node, visited_children):
|
99
|
-
return self.data
|
100
|
-
|
101
|
-
def visit_file_path(self, node, visited_children):
|
102
|
-
self.data["file_path"] = node.text.strip()
|
103
|
-
|
104
|
-
def visit_language(self, node, visited_children):
|
105
|
-
self.data["language"] = node.text.strip()
|
106
|
-
|
107
|
-
def visit_code(self, node, visited_children):
|
108
|
-
self.data["code"] = node.text.strip()
|
109
|
-
|
110
|
-
def generic_visit(self, node, visited_children):
|
111
|
-
return visited_children or node
|
112
|
-
|
113
|
-
return Visitor
|
114
|
-
|
115
|
-
@classmethod
|
116
|
-
def start_token(cls):
|
117
|
-
return "<format>"
|
118
|
-
|
119
|
-
@classmethod
|
120
|
-
def end_token(cls):
|
121
|
-
return "</format>"
|
122
|
-
|
123
|
-
|
124
|
-
# Test cases
|
125
|
-
if __name__ == "__main__":
|
126
|
-
# Test formatting
|
127
|
-
code_file = CodeFileModel(
|
128
|
-
language="Python",
|
129
|
-
file_path="src/main.py",
|
130
|
-
code="def hello():\n print('Hello, World!')",
|
131
|
-
)
|
132
|
-
formatted = CodeFileModel.format(code_file)
|
133
|
-
expected_format = """<format>
|
134
|
-
code_file_model
|
135
|
-
src/main.py
|
136
|
-
```Python
|
137
|
-
def hello():
|
138
|
-
print('Hello, World!')
|
139
|
-
```
|
140
|
-
</format>"""
|
141
|
-
assert (
|
142
|
-
formatted == expected_format
|
143
|
-
), f"Formatting failed. Expected:\n{expected_format}\nGot:\n{formatted}"
|
144
|
-
print("Formatting test passed.")
|
145
|
-
|
146
|
-
# Test parsing
|
147
|
-
parsed = CodeFileModel.parse(formatted)
|
148
|
-
assert (
|
149
|
-
parsed == code_file
|
150
|
-
), f"Parsing failed. Expected:\n{code_file}\nGot:\n{parsed}"
|
151
|
-
print("Parsing test passed.")
|
152
|
-
|
153
|
-
# Test round-trip
|
154
|
-
round_trip = CodeFileModel.parse(CodeFileModel.format(code_file))
|
155
|
-
assert (
|
156
|
-
round_trip == code_file
|
157
|
-
), f"Round-trip failed. Expected:\n{code_file}\nGot:\n{round_trip}"
|
158
|
-
print("Round-trip test passed.")
|
159
|
-
|
160
|
-
# Test with different values
|
161
|
-
code_file2 = CodeFileModel(
|
162
|
-
language="JavaScript",
|
163
|
-
file_path="src/app.js",
|
164
|
-
code="function greet() {\n console.log('Hello, World!');\n}",
|
165
|
-
)
|
166
|
-
formatted2 = CodeFileModel.format(code_file2)
|
167
|
-
parsed2 = CodeFileModel.parse(formatted2)
|
168
|
-
assert (
|
169
|
-
parsed2 == code_file2
|
170
|
-
), f"Parsing failed for different values. Expected:\n{code_file2}\nGot:\n{parsed2}"
|
171
|
-
print("Different values test passed.")
|
172
|
-
|
173
|
-
# Test tolerant parsing
|
174
|
-
tolerant_input = """<format>
|
175
|
-
code_file_model
|
176
|
-
src/main.py
|
177
|
-
|
178
|
-
``` Python
|
179
|
-
def hello():
|
180
|
-
print('Hello, World!')
|
181
|
-
```
|
182
|
-
</format>"""
|
183
|
-
parsed_tolerant = CodeFileModel.parse(tolerant_input)
|
184
|
-
expected_tolerant = CodeFileModel(
|
185
|
-
language="Python",
|
186
|
-
file_path="src/main.py",
|
187
|
-
code="def hello():\n print('Hello, World!')",
|
188
|
-
)
|
189
|
-
assert (
|
190
|
-
parsed_tolerant == expected_tolerant
|
191
|
-
), f"Tolerant parsing failed. Expected:\n{expected_tolerant}\nGot:\n{parsed_tolerant}"
|
192
|
-
print("Tolerant parsing test passed.")
|
193
|
-
|
194
|
-
print("All tests passed successfully!")
|