langroid 0.16.7__py3-none-any.whl → 0.17.1__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 +179 -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.1.dist-info}/METADATA +6 -3
- {langroid-0.16.7.dist-info → langroid-0.17.1.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.1.dist-info}/LICENSE +0 -0
- {langroid-0.16.7.dist-info → langroid-0.17.1.dist-info}/WHEEL +0 -0
@@ -1,145 +0,0 @@
|
|
1
|
-
from abc import ABC, abstractmethod
|
2
|
-
from typing import Type, TypeVar
|
3
|
-
|
4
|
-
from jinja2 import BaseLoader, Environment
|
5
|
-
from parse import parse as str_parse
|
6
|
-
from parse import with_pattern
|
7
|
-
|
8
|
-
from langroid.pydantic_v1 import BaseModel
|
9
|
-
|
10
|
-
T = TypeVar("T", bound="FormattingModel")
|
11
|
-
|
12
|
-
|
13
|
-
@with_pattern(r"[\s\S]*?")
|
14
|
-
def _match_multiline(text):
|
15
|
-
return text.strip()
|
16
|
-
|
17
|
-
|
18
|
-
class FormattingModel(BaseModel, ABC):
|
19
|
-
@classmethod
|
20
|
-
@abstractmethod
|
21
|
-
def format_spec(cls) -> str:
|
22
|
-
pass
|
23
|
-
|
24
|
-
@classmethod
|
25
|
-
@abstractmethod
|
26
|
-
def parse_spec(cls) -> str:
|
27
|
-
pass
|
28
|
-
|
29
|
-
@classmethod
|
30
|
-
@abstractmethod
|
31
|
-
def start_token(cls) -> str:
|
32
|
-
pass
|
33
|
-
|
34
|
-
@classmethod
|
35
|
-
@abstractmethod
|
36
|
-
def end_token(cls) -> str:
|
37
|
-
pass
|
38
|
-
|
39
|
-
@classmethod
|
40
|
-
def parse(cls: Type[T], text: str) -> T:
|
41
|
-
content = text.strip()[len(cls.start_token()) : -len(cls.end_token())].strip()
|
42
|
-
result = str_parse(
|
43
|
-
cls.parse_spec(),
|
44
|
-
content,
|
45
|
-
dict(multiline=_match_multiline),
|
46
|
-
case_sensitive=False,
|
47
|
-
)
|
48
|
-
if result is None:
|
49
|
-
raise ValueError(
|
50
|
-
f"Failed to parse the input string using spec: {cls.parse_spec()}\nInput: {content}"
|
51
|
-
)
|
52
|
-
return cls(**result.named)
|
53
|
-
|
54
|
-
def generate(self) -> str:
|
55
|
-
env = Environment(loader=BaseLoader(), trim_blocks=True, lstrip_blocks=True)
|
56
|
-
template = env.from_string(self.format_spec())
|
57
|
-
content = template.render(**self.dict())
|
58
|
-
return f"{self.start_token()}\n{content.strip()}\n{self.end_token()}"
|
59
|
-
|
60
|
-
|
61
|
-
class CodeFileModel(FormattingModel):
|
62
|
-
language: str
|
63
|
-
file_path: str
|
64
|
-
code: str
|
65
|
-
|
66
|
-
@classmethod
|
67
|
-
def format_spec(cls) -> str:
|
68
|
-
return (
|
69
|
-
"code_file_model\n"
|
70
|
-
"file_path: {{- file_path -}}\n"
|
71
|
-
"```{{- language -}}\n"
|
72
|
-
"{{ code }}"
|
73
|
-
"```"
|
74
|
-
)
|
75
|
-
|
76
|
-
@classmethod
|
77
|
-
def parse_spec(cls) -> str:
|
78
|
-
return "code_file_model\n" "file_path:{:s}\n" "```{:s}\n" "{:multiline}" "```"
|
79
|
-
|
80
|
-
@classmethod
|
81
|
-
def start_token(cls) -> str:
|
82
|
-
return "<format>"
|
83
|
-
|
84
|
-
@classmethod
|
85
|
-
def end_token(cls) -> str:
|
86
|
-
return "</format>"
|
87
|
-
|
88
|
-
|
89
|
-
# Test code
|
90
|
-
if __name__ == "__main__":
|
91
|
-
# Test with extra whitespace
|
92
|
-
test_string = """
|
93
|
-
<format>
|
94
|
-
code_file_model
|
95
|
-
file_path: src/main.py
|
96
|
-
``` python
|
97
|
-
def hello():
|
98
|
-
print("Hello, World!")
|
99
|
-
|
100
|
-
```
|
101
|
-
</format>
|
102
|
-
"""
|
103
|
-
|
104
|
-
parsed = CodeFileModel.parse(test_string)
|
105
|
-
print("Parsed model:")
|
106
|
-
print(parsed)
|
107
|
-
|
108
|
-
generated = parsed.generate()
|
109
|
-
print("\nGenerated string:")
|
110
|
-
print(generated)
|
111
|
-
|
112
|
-
reparsed = CodeFileModel.parse(generated)
|
113
|
-
print("\nReparsed model:")
|
114
|
-
print(reparsed)
|
115
|
-
|
116
|
-
print("\nRound trip test:")
|
117
|
-
assert parsed == reparsed, "Round trip test failed"
|
118
|
-
print("Passed!")
|
119
|
-
|
120
|
-
# Test with different values and whitespace
|
121
|
-
another_test = """
|
122
|
-
<format>
|
123
|
-
code_file_model
|
124
|
-
file_path:src/app.js
|
125
|
-
``` javascript
|
126
|
-
function greet(name) {
|
127
|
-
console.log(`Hello, ${name}!`);
|
128
|
-
}
|
129
|
-
```
|
130
|
-
</format>
|
131
|
-
"""
|
132
|
-
|
133
|
-
another_parsed = CodeFileModel.parse(another_test)
|
134
|
-
print("\nAnother parsed model:")
|
135
|
-
print(another_parsed)
|
136
|
-
|
137
|
-
another_generated = another_parsed.generate()
|
138
|
-
print("\nAnother generated string:")
|
139
|
-
print(another_generated)
|
140
|
-
|
141
|
-
print("\nAnother round trip test:")
|
142
|
-
assert another_parsed == CodeFileModel.parse(
|
143
|
-
another_generated
|
144
|
-
), "Another round trip test failed"
|
145
|
-
print("Passed!")
|
@@ -1,135 +0,0 @@
|
|
1
|
-
from pydantic import BaseModel
|
2
|
-
from abc import ABC, abstractmethod
|
3
|
-
from typing import Type, TypeVar
|
4
|
-
from jinja2 import Environment, BaseLoader
|
5
|
-
from parse import parse as str_parse, with_pattern
|
6
|
-
|
7
|
-
T = TypeVar('T', bound='FormattingModel')
|
8
|
-
|
9
|
-
@with_pattern(r'[\s\S]*?')
|
10
|
-
def _match_multiline(text):
|
11
|
-
return text.strip()
|
12
|
-
|
13
|
-
class FormattingModel(BaseModel, ABC):
|
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
|
-
@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 parse(cls: Type[T], text: str) -> T:
|
36
|
-
content = text.strip()[len(cls.start_token()):-len(cls.end_token())].strip()
|
37
|
-
result = str_parse(cls.parse_spec(), content, dict(multiline=_match_multiline), case_sensitive=False)
|
38
|
-
if result is None:
|
39
|
-
raise ValueError(f"Failed to parse the input string using spec: {cls.parse_spec()}\nInput: {content}")
|
40
|
-
return cls(**result.named)
|
41
|
-
|
42
|
-
def generate(self) -> str:
|
43
|
-
env = Environment(loader=BaseLoader(), trim_blocks=True, lstrip_blocks=True)
|
44
|
-
template = env.from_string(self.format_spec())
|
45
|
-
content = template.render(**self.dict())
|
46
|
-
return f"{self.start_token()}\n{content.strip()}\n{self.end_token()}"
|
47
|
-
|
48
|
-
class CodeFileModel(FormattingModel):
|
49
|
-
language: str
|
50
|
-
file_path: str
|
51
|
-
code: str
|
52
|
-
|
53
|
-
@classmethod
|
54
|
-
def format_spec(cls) -> str:
|
55
|
-
return (
|
56
|
-
"code_file_model\n"
|
57
|
-
"file_path: {{- file_path -}}\n"
|
58
|
-
"```{{- language -}}\n"
|
59
|
-
"{{ code }}"
|
60
|
-
"```"
|
61
|
-
)
|
62
|
-
|
63
|
-
@classmethod
|
64
|
-
def parse_spec(cls) -> str:
|
65
|
-
return (
|
66
|
-
"code_file_model\n"
|
67
|
-
"file_path:{:s}\n"
|
68
|
-
"```{:s}\n"
|
69
|
-
"{:multiline}"
|
70
|
-
"```"
|
71
|
-
)
|
72
|
-
|
73
|
-
@classmethod
|
74
|
-
def start_token(cls) -> str:
|
75
|
-
return "<format>"
|
76
|
-
|
77
|
-
@classmethod
|
78
|
-
def end_token(cls) -> str:
|
79
|
-
return "</format>"
|
80
|
-
|
81
|
-
# Test code
|
82
|
-
if __name__ == "__main__":
|
83
|
-
# Test with extra whitespace
|
84
|
-
test_string = """
|
85
|
-
<format>
|
86
|
-
code_file_model
|
87
|
-
file_path: src/main.py
|
88
|
-
``` python
|
89
|
-
def hello():
|
90
|
-
print("Hello, World!")
|
91
|
-
|
92
|
-
```
|
93
|
-
</format>
|
94
|
-
"""
|
95
|
-
|
96
|
-
parsed = CodeFileModel.parse(test_string)
|
97
|
-
print("Parsed model:")
|
98
|
-
print(parsed)
|
99
|
-
|
100
|
-
generated = parsed.generate()
|
101
|
-
print("\nGenerated string:")
|
102
|
-
print(generated)
|
103
|
-
|
104
|
-
reparsed = CodeFileModel.parse(generated)
|
105
|
-
print("\nReparsed model:")
|
106
|
-
print(reparsed)
|
107
|
-
|
108
|
-
print("\nRound trip test:")
|
109
|
-
assert parsed == reparsed, "Round trip test failed"
|
110
|
-
print("Passed!")
|
111
|
-
|
112
|
-
# Test with different values and whitespace
|
113
|
-
another_test = """
|
114
|
-
<format>
|
115
|
-
code_file_model
|
116
|
-
file_path:src/app.js
|
117
|
-
``` javascript
|
118
|
-
function greet(name) {
|
119
|
-
console.log(`Hello, ${name}!`);
|
120
|
-
}
|
121
|
-
```
|
122
|
-
</format>
|
123
|
-
"""
|
124
|
-
|
125
|
-
another_parsed = CodeFileModel.parse(another_test)
|
126
|
-
print("\nAnother parsed model:")
|
127
|
-
print(another_parsed)
|
128
|
-
|
129
|
-
another_generated = another_parsed.generate()
|
130
|
-
print("\nAnother generated string:")
|
131
|
-
print(another_generated)
|
132
|
-
|
133
|
-
print("\nAnother round trip test:")
|
134
|
-
assert another_parsed == CodeFileModel.parse(another_generated), "Another round trip test failed"
|
135
|
-
print("Passed!")
|
File without changes
|
@@ -1,168 +0,0 @@
|
|
1
|
-
from abc import ABC, abstractmethod
|
2
|
-
|
3
|
-
from lark import Lark, Transformer, v_args
|
4
|
-
|
5
|
-
from langroid.pydantic_v1 import BaseModel
|
6
|
-
|
7
|
-
|
8
|
-
class FormattingModel(BaseModel, ABC):
|
9
|
-
@classmethod
|
10
|
-
@abstractmethod
|
11
|
-
def format_spec(cls) -> str:
|
12
|
-
pass
|
13
|
-
|
14
|
-
@classmethod
|
15
|
-
@abstractmethod
|
16
|
-
def parse_spec(cls) -> str:
|
17
|
-
pass
|
18
|
-
|
19
|
-
@classmethod
|
20
|
-
@abstractmethod
|
21
|
-
def start_token(cls) -> str:
|
22
|
-
pass
|
23
|
-
|
24
|
-
@classmethod
|
25
|
-
@abstractmethod
|
26
|
-
def end_token(cls) -> str:
|
27
|
-
pass
|
28
|
-
|
29
|
-
@classmethod
|
30
|
-
def format(cls, instance: "FormattingModel") -> str:
|
31
|
-
spec = cls.format_spec()
|
32
|
-
formatted = spec.format(**instance.dict())
|
33
|
-
return f"{cls.start_token()}\n{formatted}\n{cls.end_token()}"
|
34
|
-
|
35
|
-
@classmethod
|
36
|
-
def parse(cls, formatted_string: str) -> "FormattingModel":
|
37
|
-
lines = formatted_string.strip().split("\n")
|
38
|
-
if lines[0] != cls.start_token() or lines[-1] != cls.end_token():
|
39
|
-
raise ValueError("Invalid start or end token")
|
40
|
-
content = "\n".join(lines[1:-1])
|
41
|
-
|
42
|
-
parser = Lark(cls.parse_spec(), start="start", parser="lalr")
|
43
|
-
|
44
|
-
@v_args(inline=True)
|
45
|
-
class TreeToDict(Transformer):
|
46
|
-
def start(self, _, file_path, code_block):
|
47
|
-
return {
|
48
|
-
"file_path": file_path,
|
49
|
-
"language": code_block.children[1],
|
50
|
-
"code": code_block.children[3],
|
51
|
-
}
|
52
|
-
|
53
|
-
def file_path(self, path):
|
54
|
-
return path.value
|
55
|
-
|
56
|
-
def language(self, lang):
|
57
|
-
return lang.value
|
58
|
-
|
59
|
-
def code(self, code):
|
60
|
-
return code.value.strip()
|
61
|
-
|
62
|
-
tree = parser.parse(content)
|
63
|
-
data = TreeToDict().transform(tree)
|
64
|
-
return cls(**data)
|
65
|
-
|
66
|
-
|
67
|
-
class CodeFileModel(FormattingModel):
|
68
|
-
language: str
|
69
|
-
file_path: str
|
70
|
-
code: str
|
71
|
-
|
72
|
-
@classmethod
|
73
|
-
def format_spec(cls):
|
74
|
-
return "code_file_model\n{file_path}\n```{language}\n{code}\n```"
|
75
|
-
|
76
|
-
@classmethod
|
77
|
-
def parse_spec(cls):
|
78
|
-
return """
|
79
|
-
start: "code_file_model" NEWLINE file_path NEWLINE code_block
|
80
|
-
file_path: /[^\\n]+/
|
81
|
-
code_block: "```" language NEWLINE code "```"
|
82
|
-
language: /[^\\n]+/
|
83
|
-
code: /.+?(?=\\n```)/s
|
84
|
-
NEWLINE: "\\n"
|
85
|
-
%import common.WS
|
86
|
-
%ignore WS
|
87
|
-
"""
|
88
|
-
|
89
|
-
@classmethod
|
90
|
-
def start_token(cls):
|
91
|
-
return "<format>"
|
92
|
-
|
93
|
-
@classmethod
|
94
|
-
def end_token(cls):
|
95
|
-
return "</format>"
|
96
|
-
|
97
|
-
|
98
|
-
# Test cases
|
99
|
-
if __name__ == "__main__":
|
100
|
-
# Test formatting
|
101
|
-
code_file = CodeFileModel(
|
102
|
-
language="Python",
|
103
|
-
file_path="src/main.py",
|
104
|
-
code="def hello():\n print('Hello, World!')",
|
105
|
-
)
|
106
|
-
formatted = CodeFileModel.format(code_file)
|
107
|
-
expected_format = """<format>
|
108
|
-
code_file_model
|
109
|
-
src/main.py
|
110
|
-
```Python
|
111
|
-
def hello():
|
112
|
-
print('Hello, World!')
|
113
|
-
```
|
114
|
-
</format>"""
|
115
|
-
assert (
|
116
|
-
formatted == expected_format
|
117
|
-
), f"Formatting failed. Expected:\n{expected_format}\nGot:\n{formatted}"
|
118
|
-
print("Formatting test passed.")
|
119
|
-
|
120
|
-
# Test parsing
|
121
|
-
parsed = CodeFileModel.parse(formatted)
|
122
|
-
assert (
|
123
|
-
parsed == code_file
|
124
|
-
), f"Parsing failed. Expected:\n{code_file}\nGot:\n{parsed}"
|
125
|
-
print("Parsing test passed.")
|
126
|
-
|
127
|
-
# Test round-trip
|
128
|
-
round_trip = CodeFileModel.parse(CodeFileModel.format(code_file))
|
129
|
-
assert (
|
130
|
-
round_trip == code_file
|
131
|
-
), f"Round-trip failed. Expected:\n{code_file}\nGot:\n{round_trip}"
|
132
|
-
print("Round-trip test passed.")
|
133
|
-
|
134
|
-
# Test with different values
|
135
|
-
code_file2 = CodeFileModel(
|
136
|
-
language="JavaScript",
|
137
|
-
file_path="src/app.js",
|
138
|
-
code="function greet() {\n console.log('Hello, World!');\n}",
|
139
|
-
)
|
140
|
-
formatted2 = CodeFileModel.format(code_file2)
|
141
|
-
parsed2 = CodeFileModel.parse(formatted2)
|
142
|
-
assert (
|
143
|
-
parsed2 == code_file2
|
144
|
-
), f"Parsing failed for different values. Expected:\n{code_file2}\nGot:\n{parsed2}"
|
145
|
-
print("Different values test passed.")
|
146
|
-
|
147
|
-
# Test tolerant parsing
|
148
|
-
tolerant_input = """<format>
|
149
|
-
code_file_model
|
150
|
-
src/main.py
|
151
|
-
|
152
|
-
``` Python
|
153
|
-
def hello():
|
154
|
-
print('Hello, World!')
|
155
|
-
```
|
156
|
-
</format>"""
|
157
|
-
parsed_tolerant = CodeFileModel.parse(tolerant_input)
|
158
|
-
expected_tolerant = CodeFileModel(
|
159
|
-
language="Python",
|
160
|
-
file_path="src/main.py",
|
161
|
-
code="def hello():\n print('Hello, World!')",
|
162
|
-
)
|
163
|
-
assert (
|
164
|
-
parsed_tolerant == expected_tolerant
|
165
|
-
), f"Tolerant parsing failed. Expected:\n{expected_tolerant}\nGot:\n{parsed_tolerant}"
|
166
|
-
print("Tolerant parsing test passed.")
|
167
|
-
|
168
|
-
print("All tests passed successfully!")
|
@@ -1,105 +0,0 @@
|
|
1
|
-
from abc import ABC, abstractmethod
|
2
|
-
from typing import ClassVar
|
3
|
-
|
4
|
-
from parse import parse
|
5
|
-
|
6
|
-
from langroid.pydantic_v1 import BaseModel
|
7
|
-
|
8
|
-
|
9
|
-
class FormattingModel(BaseModel, ABC):
|
10
|
-
class Config:
|
11
|
-
arbitrary_types_allowed = True
|
12
|
-
|
13
|
-
START_TOKEN: ClassVar[str] = "<format>"
|
14
|
-
END_TOKEN: ClassVar[str] = "</format>"
|
15
|
-
|
16
|
-
@classmethod
|
17
|
-
@abstractmethod
|
18
|
-
def format_spec(cls) -> str:
|
19
|
-
pass
|
20
|
-
|
21
|
-
@classmethod
|
22
|
-
@abstractmethod
|
23
|
-
def parse_spec(cls) -> str:
|
24
|
-
pass
|
25
|
-
|
26
|
-
@classmethod
|
27
|
-
def format(cls, instance: "FormattingModel") -> str:
|
28
|
-
template = f"{cls.START_TOKEN}\n{{content}}\n{cls.END_TOKEN}"
|
29
|
-
spec_template = cls.format_spec()
|
30
|
-
formatted_content = spec_template.format(**instance.dict())
|
31
|
-
return template.format(content=formatted_content)
|
32
|
-
|
33
|
-
@classmethod
|
34
|
-
def parse(cls, formatted_string: str) -> "FormattingModel":
|
35
|
-
outer_template = f"{cls.START_TOKEN}\n{{content}}\n{cls.END_TOKEN}"
|
36
|
-
outer_parsed = parse(outer_template, formatted_string, case_sensitive=False)
|
37
|
-
if not outer_parsed:
|
38
|
-
raise ValueError("Invalid outer format")
|
39
|
-
|
40
|
-
content = outer_parsed["content"]
|
41
|
-
parse_template = cls.parse_spec()
|
42
|
-
parsed = parse(parse_template, content, case_sensitive=False)
|
43
|
-
if not parsed:
|
44
|
-
raise ValueError(
|
45
|
-
f"Failed to parse content:\n{content}\nusing spec:\n{parse_template}"
|
46
|
-
)
|
47
|
-
|
48
|
-
return cls(**parsed.named)
|
49
|
-
|
50
|
-
|
51
|
-
class PersonModel(FormattingModel):
|
52
|
-
name: str
|
53
|
-
age: int
|
54
|
-
city: str
|
55
|
-
|
56
|
-
START_TOKEN: ClassVar[str] = "<person>"
|
57
|
-
END_TOKEN: ClassVar[str] = "</person>"
|
58
|
-
|
59
|
-
@classmethod
|
60
|
-
def format_spec(cls):
|
61
|
-
return "name: {name}\n{age} is the age\nlives in {city}"
|
62
|
-
|
63
|
-
@classmethod
|
64
|
-
def parse_spec(cls):
|
65
|
-
return "name: {name:S}\n{age:d} is the age\nlives in {city:S}"
|
66
|
-
|
67
|
-
|
68
|
-
# Tests
|
69
|
-
if __name__ == "__main__":
|
70
|
-
# Test instance
|
71
|
-
person = PersonModel(name="John Doe", age=30, city="New York")
|
72
|
-
|
73
|
-
# Test formatting
|
74
|
-
formatted_string = PersonModel.format(person)
|
75
|
-
print("Formatted string:")
|
76
|
-
print(formatted_string)
|
77
|
-
assert formatted_string == (
|
78
|
-
"<person>\n"
|
79
|
-
"name: John Doe\n"
|
80
|
-
"30 is the age\n"
|
81
|
-
"lives in New York\n"
|
82
|
-
"</person>"
|
83
|
-
)
|
84
|
-
|
85
|
-
# Test parsing
|
86
|
-
parsed_person = PersonModel.parse(formatted_string)
|
87
|
-
print("\nParsed person:", parsed_person)
|
88
|
-
assert parsed_person == person
|
89
|
-
|
90
|
-
# Test round trip
|
91
|
-
round_trip_person = PersonModel.parse(PersonModel.format(person))
|
92
|
-
assert round_trip_person == person
|
93
|
-
|
94
|
-
# Test parsing with extra whitespace and different casing
|
95
|
-
extra_whitespace_string = """
|
96
|
-
<PERSON>
|
97
|
-
Name: John Doe
|
98
|
-
30 IS THE AGE
|
99
|
-
Lives in New York
|
100
|
-
</person>
|
101
|
-
"""
|
102
|
-
parsed_extra_whitespace = PersonModel.parse(extra_whitespace_string)
|
103
|
-
assert parsed_extra_whitespace == person
|
104
|
-
|
105
|
-
print("All tests passed!")
|
@@ -1,98 +0,0 @@
|
|
1
|
-
from abc import ABC, abstractmethod
|
2
|
-
from typing import ClassVar
|
3
|
-
from pydantic import BaseModel
|
4
|
-
from parse import parse
|
5
|
-
|
6
|
-
class FormattingModel(BaseModel, ABC):
|
7
|
-
class Config:
|
8
|
-
arbitrary_types_allowed = True
|
9
|
-
|
10
|
-
START_TOKEN: ClassVar[str] = "<format>"
|
11
|
-
END_TOKEN: ClassVar[str] = "</format>"
|
12
|
-
|
13
|
-
@classmethod
|
14
|
-
@abstractmethod
|
15
|
-
def format_spec(cls) -> str:
|
16
|
-
pass
|
17
|
-
|
18
|
-
@classmethod
|
19
|
-
@abstractmethod
|
20
|
-
def parse_spec(cls) -> str:
|
21
|
-
pass
|
22
|
-
|
23
|
-
@classmethod
|
24
|
-
def format(cls, instance: 'FormattingModel') -> str:
|
25
|
-
template = f"{cls.START_TOKEN}\n{{content}}\n{cls.END_TOKEN}"
|
26
|
-
spec_template = cls.format_spec()
|
27
|
-
formatted_content = spec_template.format(**instance.dict())
|
28
|
-
return template.format(content=formatted_content)
|
29
|
-
|
30
|
-
@classmethod
|
31
|
-
def parse(cls, formatted_string: str) -> 'FormattingModel':
|
32
|
-
outer_template = f"{cls.START_TOKEN}\n{{content}}\n{cls.END_TOKEN}"
|
33
|
-
outer_parsed = parse(outer_template, formatted_string, case_sensitive=False)
|
34
|
-
if not outer_parsed:
|
35
|
-
raise ValueError("Invalid outer format")
|
36
|
-
|
37
|
-
content = outer_parsed['content']
|
38
|
-
parse_template = cls.parse_spec()
|
39
|
-
parsed = parse(parse_template, content, case_sensitive=False)
|
40
|
-
if not parsed:
|
41
|
-
raise ValueError(f"Failed to parse content:\n{content}\nusing spec:\n{parse_template}")
|
42
|
-
|
43
|
-
return cls(**parsed.named)
|
44
|
-
|
45
|
-
class PersonModel(FormattingModel):
|
46
|
-
name: str
|
47
|
-
age: int
|
48
|
-
city: str
|
49
|
-
|
50
|
-
START_TOKEN: ClassVar[str] = "<person>"
|
51
|
-
END_TOKEN: ClassVar[str] = "</person>"
|
52
|
-
|
53
|
-
@classmethod
|
54
|
-
def format_spec(cls):
|
55
|
-
return "name: {name}\n{age} is the age\nlives in {city}"
|
56
|
-
|
57
|
-
@classmethod
|
58
|
-
def parse_spec(cls):
|
59
|
-
return "name: {name:S}\n{age:d} is the age\nlives in {city:S}"
|
60
|
-
|
61
|
-
# Tests
|
62
|
-
if __name__ == "__main__":
|
63
|
-
# Test instance
|
64
|
-
person = PersonModel(name="John Doe", age=30, city="New York")
|
65
|
-
|
66
|
-
# Test formatting
|
67
|
-
formatted_string = PersonModel.format(person)
|
68
|
-
print("Formatted string:")
|
69
|
-
print(formatted_string)
|
70
|
-
assert formatted_string == (
|
71
|
-
"<person>\n"
|
72
|
-
"name: John Doe\n"
|
73
|
-
"30 is the age\n"
|
74
|
-
"lives in New York\n"
|
75
|
-
"</person>"
|
76
|
-
)
|
77
|
-
|
78
|
-
# Test parsing
|
79
|
-
parsed_person = PersonModel.parse(formatted_string)
|
80
|
-
print("\nParsed person:", parsed_person)
|
81
|
-
assert parsed_person == person
|
82
|
-
|
83
|
-
# Test round trip
|
84
|
-
round_trip_person = PersonModel.parse(PersonModel.format(person))
|
85
|
-
assert round_trip_person == person
|
86
|
-
|
87
|
-
# Test parsing with extra whitespace and different casing
|
88
|
-
extra_whitespace_string = """
|
89
|
-
<PERSON>
|
90
|
-
Name: John Doe
|
91
|
-
30 IS THE AGE
|
92
|
-
Lives in New York
|
93
|
-
</person>
|
94
|
-
"""
|
95
|
-
parsed_extra_whitespace = PersonModel.parse(extra_whitespace_string)
|
96
|
-
assert parsed_extra_whitespace == person
|
97
|
-
|
98
|
-
print("All tests passed!")
|