langroid 0.16.5__py3-none-any.whl → 0.16.7__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.
Files changed (80) hide show
  1. langroid/agent/md_tool_message_grammar.py +455 -0
  2. langroid/agent/tools/code_file_tool_parse.py +150 -0
  3. langroid/agent/tools/code_file_tool_pyparsing.py +194 -0
  4. langroid/agent/tools/code_file_tool_pyparsing2.py +199 -0
  5. langroid/agent/tools/formatted_model_custom.py +150 -0
  6. langroid/agent/tools/formatted_model_custom2.py +168 -0
  7. langroid/agent/tools/formatted_model_custom3.py +279 -0
  8. langroid/agent/tools/formatted_model_custom4.py +395 -0
  9. langroid/agent/tools/formatted_model_jinja.py +133 -0
  10. langroid/agent/tools/formatted_model_jinja.py-e +122 -0
  11. langroid/agent/tools/formatted_model_jinja2.py +145 -0
  12. langroid/agent/tools/formatted_model_jinja2.py-e +135 -0
  13. langroid/agent/tools/formatted_model_lark.py +0 -0
  14. langroid/agent/tools/formatted_model_lark2.py +168 -0
  15. langroid/agent/tools/formatted_model_parse.py +105 -0
  16. langroid/agent/tools/formatted_model_parse.py-e +98 -0
  17. langroid/agent/tools/formatted_model_parse2.py +113 -0
  18. langroid/agent/tools/formatted_model_parse2.py-e +109 -0
  19. langroid/agent/tools/formatted_model_parse3.py +114 -0
  20. langroid/agent/tools/formatted_model_parse3.py-e +110 -0
  21. langroid/agent/tools/formatted_model_parsimon.py +194 -0
  22. langroid/agent/tools/formatted_model_parsimon.py-e +186 -0
  23. langroid/agent/tools/formatted_model_pyparsing.py +169 -0
  24. langroid/agent/tools/formatted_model_pyparsing.py-e +149 -0
  25. langroid/agent/tools/formatted_model_pyparsing2.py +159 -0
  26. langroid/agent/tools/formatted_model_pyparsing2.py-e +143 -0
  27. langroid/agent/tools/formatted_model_pyparsing3.py +133 -0
  28. langroid/agent/tools/formatted_model_pyparsing3.py-e +121 -0
  29. langroid/agent/tools/formatted_model_pyparsing4.py +213 -0
  30. langroid/agent/tools/formatted_model_pyparsing4.py-e +176 -0
  31. langroid/agent/tools/formatted_model_pyparsing5.py +173 -0
  32. langroid/agent/tools/formatted_model_pyparsing5.py-e +142 -0
  33. langroid/agent/tools/formatted_model_regex.py +246 -0
  34. langroid/agent/tools/formatted_model_regex.py-e +248 -0
  35. langroid/agent/tools/formatted_model_regex2.py +250 -0
  36. langroid/agent/tools/formatted_model_regex2.py-e +253 -0
  37. langroid/agent/tools/formatted_model_tatsu.py +172 -0
  38. langroid/agent/tools/formatted_model_tatsu.py-e +160 -0
  39. langroid/agent/tools/formatted_model_template.py +217 -0
  40. langroid/agent/tools/formatted_model_template.py-e +200 -0
  41. langroid/agent/tools/formatted_model_xml.py +178 -0
  42. langroid/agent/tools/formatted_model_xml2.py +178 -0
  43. langroid/agent/tools/formatted_model_xml3.py +132 -0
  44. langroid/agent/tools/formatted_model_xml4.py +130 -0
  45. langroid/agent/tools/formatted_model_xml5.py +130 -0
  46. langroid/agent/tools/formatted_model_xml6.py +113 -0
  47. langroid/agent/tools/formatted_model_xml7.py +117 -0
  48. langroid/agent/tools/formatted_model_xml8.py +164 -0
  49. langroid/agent/tools/generic_tool.py +165 -0
  50. langroid/agent/tools/generic_tool_tatsu.py +275 -0
  51. langroid/agent/tools/grammar_based_model.py +132 -0
  52. langroid/agent/tools/grammar_based_model.py-e +128 -0
  53. langroid/agent/tools/grammar_based_model_lark.py +156 -0
  54. langroid/agent/tools/grammar_based_model_lark.py-e +153 -0
  55. langroid/agent/tools/grammar_based_model_parse.py +86 -0
  56. langroid/agent/tools/grammar_based_model_parse.py-e +80 -0
  57. langroid/agent/tools/grammar_based_model_parsimonious.py +129 -0
  58. langroid/agent/tools/grammar_based_model_parsimonious.py-e +120 -0
  59. langroid/agent/tools/grammar_based_model_pyparsing.py +105 -0
  60. langroid/agent/tools/grammar_based_model_pyparsing.py-e +103 -0
  61. langroid/agent/tools/grammar_based_model_regex.py +139 -0
  62. langroid/agent/tools/grammar_based_model_regex.py-e +130 -0
  63. langroid/agent/tools/grammar_based_model_regex2.py +124 -0
  64. langroid/agent/tools/grammar_based_model_regex2.py-e +116 -0
  65. langroid/agent/tools/grammar_based_model_tatsu.py +80 -0
  66. langroid/agent/tools/grammar_based_model_tatsu.py-e +77 -0
  67. langroid/agent/tools/lark_earley_example.py +135 -0
  68. langroid/agent/tools/lark_earley_example.py-e +117 -0
  69. langroid/agent/tools/lark_example.py +72 -0
  70. langroid/agent/tools/parse_example.py +76 -0
  71. langroid/agent/tools/parse_example2.py +87 -0
  72. langroid/agent/tools/parse_example3.py +42 -0
  73. langroid/agent/tools/parse_test.py +791 -0
  74. langroid/agent/xml_tool_message.py +106 -0
  75. langroid/language_models/openai_gpt.py +6 -1
  76. {langroid-0.16.5.dist-info → langroid-0.16.7.dist-info}/METADATA +1 -1
  77. {langroid-0.16.5.dist-info → langroid-0.16.7.dist-info}/RECORD +80 -6
  78. pyproject.toml +1 -1
  79. {langroid-0.16.5.dist-info → langroid-0.16.7.dist-info}/LICENSE +0 -0
  80. {langroid-0.16.5.dist-info → langroid-0.16.7.dist-info}/WHEEL +0 -0
@@ -0,0 +1,159 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Dict, List, Type, TypeVar
3
+
4
+ from pyparsing import (
5
+ Group,
6
+ LineEnd,
7
+ OneOrMore,
8
+ ParseException,
9
+ ParserElement,
10
+ SkipTo,
11
+ Suppress,
12
+ )
13
+
14
+ from langroid.pydantic_v1 import BaseModel
15
+
16
+ T = TypeVar("T", bound="FormattingModel")
17
+
18
+
19
+ class FormatElement:
20
+ def __init__(self, key: str, prefix: str = "", suffix: str = ""):
21
+ self.key = key
22
+ self.prefix = prefix
23
+ self.suffix = suffix
24
+
25
+ def to_parser(self) -> ParserElement:
26
+ return Group(
27
+ Suppress(self.prefix)
28
+ + SkipTo(Suppress(self.suffix + LineEnd())).set_results_name(self.key)
29
+ )
30
+
31
+ def to_template(self) -> str:
32
+ return f"{self.prefix}{{{self.key}}}{self.suffix}\n"
33
+
34
+
35
+ class FormattingModel(BaseModel, ABC):
36
+ @classmethod
37
+ @abstractmethod
38
+ def format_elements(cls) -> List[FormatElement]:
39
+ pass
40
+
41
+ @classmethod
42
+ @abstractmethod
43
+ def start_token(cls) -> str:
44
+ pass
45
+
46
+ @classmethod
47
+ @abstractmethod
48
+ def end_token(cls) -> str:
49
+ pass
50
+
51
+ @classmethod
52
+ def format_spec(cls) -> ParserElement:
53
+ return Dict(OneOrMore([elem.to_parser() for elem in cls.format_elements()]))
54
+
55
+ @classmethod
56
+ def parse(cls: Type[T], text: str) -> T:
57
+ content = text.strip()[len(cls.start_token()) : -len(cls.end_token())].strip()
58
+ try:
59
+ parsed = cls.format_spec().parseString(content, parseAll=True)
60
+ data = {
61
+ elem.key.lower(): parsed[elem.key][0] for elem in cls.format_elements()
62
+ }
63
+ return cls(**data)
64
+ except ParseException as e:
65
+ print(f"Parsing error: {e}")
66
+ raise
67
+
68
+ def generate(self) -> str:
69
+ template = "".join(elem.to_template() for elem in self.format_elements())
70
+ for elem in self.format_elements():
71
+ value = getattr(self, elem.key.lower())
72
+ template = template.replace(f"{{{elem.key}}}", str(value))
73
+ return f"{self.start_token()}\n{template.strip()}\n{self.end_token()}"
74
+
75
+
76
+ class MyFormattedModel(FormattingModel):
77
+ name: str
78
+ age: int
79
+ city: str
80
+
81
+ @classmethod
82
+ def format_elements(cls) -> List[FormatElement]:
83
+ return [
84
+ FormatElement("NAME", prefix="name: ", suffix=""),
85
+ FormatElement("AGE", prefix="", suffix=" is the age"),
86
+ FormatElement("CITY", prefix="lives in ", suffix=""),
87
+ ]
88
+
89
+ @classmethod
90
+ def start_token(cls) -> str:
91
+ return "<format>"
92
+
93
+ @classmethod
94
+ def end_token(cls) -> str:
95
+ return "</format>"
96
+
97
+
98
+ class CodeFileModel(FormattingModel):
99
+ language: str
100
+ file_path: str
101
+ code: str
102
+
103
+ @classmethod
104
+ def format_elements(cls) -> List[FormatElement]:
105
+ return [
106
+ FormatElement("MODEL", prefix="code_file_model", suffix=""),
107
+ FormatElement("FILE_PATH", prefix="file_path: ", suffix=""),
108
+ FormatElement("LANGUAGE", prefix="```", suffix=""),
109
+ FormatElement("CODE", prefix="", suffix="```"),
110
+ ]
111
+
112
+ @classmethod
113
+ def start_token(cls) -> str:
114
+ return "<format>"
115
+
116
+ @classmethod
117
+ def end_token(cls) -> str:
118
+ return "</format>"
119
+
120
+
121
+ if __name__ == "__main__":
122
+ # Test MyFormattedModel
123
+ model = MyFormattedModel(name="John", age=30, city="Tokyo")
124
+ generated = model.generate()
125
+ print("Generated MyFormattedModel string:")
126
+ print(generated)
127
+ print()
128
+
129
+ parsed = MyFormattedModel.parse(generated)
130
+ print("Parsed MyFormattedModel object:")
131
+ print(parsed)
132
+ print()
133
+
134
+ print("MyFormattedModel Round-trip test:")
135
+ assert model == parsed, "MyFormattedModel: Original != Parsed"
136
+ print("Passed!")
137
+ print()
138
+
139
+ # Test CodeFileModel
140
+ code_model = CodeFileModel(
141
+ language="python",
142
+ file_path="src/main.py",
143
+ code='def hello():\n print("Hello, World!")',
144
+ )
145
+ code_generated = code_model.generate()
146
+ print("Generated CodeFileModel string:")
147
+ print(code_generated)
148
+ print()
149
+
150
+ code_parsed = CodeFileModel.parse(code_generated)
151
+ print("Parsed CodeFileModel object:")
152
+ print(code_parsed)
153
+ print()
154
+
155
+ print("CodeFileModel Round-trip test:")
156
+ assert code_model == code_parsed, "CodeFileModel: Original != Parsed"
157
+ print("Passed!")
158
+
159
+ print("\nAll tests passed successfully!")
@@ -0,0 +1,143 @@
1
+ from pydantic import BaseModel
2
+ from abc import ABC, abstractmethod
3
+ from typing import Dict, Type, TypeVar, List
4
+ from pyparsing import (
5
+ Word, alphanums, Suppress, SkipTo, LineEnd,
6
+ QuotedString, delimitedList, Group, OneOrMore, ParseException,
7
+ ParserElement, Regex, Literal, Optional, White, Dict
8
+ )
9
+
10
+ T = TypeVar('T', bound='FormattingModel')
11
+
12
+ class FormatElement:
13
+ def __init__(self, key: str, prefix: str = "", suffix: str = ""):
14
+ self.key = key
15
+ self.prefix = prefix
16
+ self.suffix = suffix
17
+
18
+ def to_parser(self) -> ParserElement:
19
+ return Group(Suppress(self.prefix) + SkipTo(Suppress(self.suffix + LineEnd())).set_results_name(self.key))
20
+
21
+ def to_template(self) -> str:
22
+ return f"{self.prefix}{{{self.key}}}{self.suffix}\n"
23
+
24
+ class FormattingModel(BaseModel, ABC):
25
+ @classmethod
26
+ @abstractmethod
27
+ def format_elements(cls) -> List[FormatElement]:
28
+ pass
29
+
30
+ @classmethod
31
+ @abstractmethod
32
+ def start_token(cls) -> str:
33
+ pass
34
+
35
+ @classmethod
36
+ @abstractmethod
37
+ def end_token(cls) -> str:
38
+ pass
39
+
40
+ @classmethod
41
+ def format_spec(cls) -> ParserElement:
42
+ return Dict(OneOrMore([elem.to_parser() for elem in cls.format_elements()]))
43
+
44
+ @classmethod
45
+ def parse(cls: Type[T], text: str) -> T:
46
+ content = text.strip()[len(cls.start_token()):-len(cls.end_token())].strip()
47
+ try:
48
+ parsed = cls.format_spec().parseString(content, parseAll=True)
49
+ data = {elem.key.lower(): parsed[elem.key][0] for elem in cls.format_elements()}
50
+ return cls(**data)
51
+ except ParseException as e:
52
+ print(f"Parsing error: {e}")
53
+ raise
54
+
55
+ def generate(self) -> str:
56
+ template = "".join(elem.to_template() for elem in self.format_elements())
57
+ for elem in self.format_elements():
58
+ value = getattr(self, elem.key.lower())
59
+ template = template.replace(f"{{{elem.key}}}", str(value))
60
+ return f"{self.start_token()}\n{template.strip()}\n{self.end_token()}"
61
+
62
+ class MyFormattedModel(FormattingModel):
63
+ name: str
64
+ age: int
65
+ city: str
66
+
67
+ @classmethod
68
+ def format_elements(cls) -> List[FormatElement]:
69
+ return [
70
+ FormatElement("NAME", prefix="name: ", suffix=""),
71
+ FormatElement("AGE", prefix="", suffix=" is the age"),
72
+ FormatElement("CITY", prefix="lives in ", suffix="")
73
+ ]
74
+
75
+ @classmethod
76
+ def start_token(cls) -> str:
77
+ return "<format>"
78
+
79
+ @classmethod
80
+ def end_token(cls) -> str:
81
+ return "</format>"
82
+
83
+ class CodeFileModel(FormattingModel):
84
+ language: str
85
+ file_path: str
86
+ code: str
87
+
88
+ @classmethod
89
+ def format_elements(cls) -> List[FormatElement]:
90
+ return [
91
+ FormatElement("MODEL", prefix="code_file_model", suffix=""),
92
+ FormatElement("FILE_PATH", prefix="file_path: ", suffix=""),
93
+ FormatElement("LANGUAGE", prefix="```", suffix=""),
94
+ FormatElement("CODE", prefix="", suffix="```")
95
+ ]
96
+
97
+ @classmethod
98
+ def start_token(cls) -> str:
99
+ return "<format>"
100
+
101
+ @classmethod
102
+ def end_token(cls) -> str:
103
+ return "</format>"
104
+
105
+ if __name__ == "__main__":
106
+ # Test MyFormattedModel
107
+ model = MyFormattedModel(name="John", age=30, city="Tokyo")
108
+ generated = model.generate()
109
+ print("Generated MyFormattedModel string:")
110
+ print(generated)
111
+ print()
112
+
113
+ parsed = MyFormattedModel.parse(generated)
114
+ print("Parsed MyFormattedModel object:")
115
+ print(parsed)
116
+ print()
117
+
118
+ print("MyFormattedModel Round-trip test:")
119
+ assert model == parsed, "MyFormattedModel: Original != Parsed"
120
+ print("Passed!")
121
+ print()
122
+
123
+ # Test CodeFileModel
124
+ code_model = CodeFileModel(
125
+ language="python",
126
+ file_path="src/main.py",
127
+ code="def hello():\n print(\"Hello, World!\")"
128
+ )
129
+ code_generated = code_model.generate()
130
+ print("Generated CodeFileModel string:")
131
+ print(code_generated)
132
+ print()
133
+
134
+ code_parsed = CodeFileModel.parse(code_generated)
135
+ print("Parsed CodeFileModel object:")
136
+ print(code_parsed)
137
+ print()
138
+
139
+ print("CodeFileModel Round-trip test:")
140
+ assert code_model == code_parsed, "CodeFileModel: Original != Parsed"
141
+ print("Passed!")
142
+
143
+ print("\nAll tests passed successfully!")
@@ -0,0 +1,133 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ from pyparsing import (
4
+ LineEnd,
5
+ SkipTo,
6
+ Suppress,
7
+ Word,
8
+ alphas,
9
+ )
10
+
11
+ from langroid.pydantic_v1 import BaseModel
12
+
13
+
14
+ class FormattingModel(BaseModel, ABC):
15
+ @classmethod
16
+ @abstractmethod
17
+ def format_spec(cls):
18
+ pass
19
+
20
+ @classmethod
21
+ @abstractmethod
22
+ def parse_spec(cls):
23
+ pass
24
+
25
+ @classmethod
26
+ @abstractmethod
27
+ def start_token(cls) -> str:
28
+ pass
29
+
30
+ @classmethod
31
+ @abstractmethod
32
+ def end_token(cls) -> str:
33
+ pass
34
+
35
+ @classmethod
36
+ def format(cls, instance: "FormattingModel") -> str:
37
+ spec = cls.format_spec()
38
+ formatted = spec.format(**instance.dict())
39
+ return f"{cls.start_token()}\n{formatted}\n{cls.end_token()}"
40
+
41
+ @classmethod
42
+ def parse(cls, formatted_string: str) -> "FormattingModel":
43
+ lines = formatted_string.strip().split("\n")
44
+ if lines[0] != cls.start_token() or lines[-1] != cls.end_token():
45
+ raise ValueError("Invalid start or end token")
46
+ content = "\n".join(lines[1:-1])
47
+
48
+ spec = cls.parse_spec()
49
+ parsed = spec.parseString(content, parseAll=True)
50
+ return cls(**parsed.asDict())
51
+
52
+
53
+ class CodeFileModel(FormattingModel):
54
+ language: str
55
+ file_path: str
56
+ code: str
57
+
58
+ @classmethod
59
+ def format_spec(cls):
60
+ return "code_file_model\n{file_path}\n```{language}\n{code}\n```"
61
+
62
+ @classmethod
63
+ def parse_spec(cls):
64
+ header = Suppress("code_file_model") + LineEnd()
65
+ file_path = SkipTo(LineEnd()).setResultsName("file_path")
66
+ language = Suppress("```") + Word(alphas).setResultsName("language") + LineEnd()
67
+ code = (
68
+ SkipTo("```")
69
+ .setResultsName("code")
70
+ .setParseAction(lambda s, l, t: t[0].rstrip())
71
+ )
72
+
73
+ return header + file_path + language + code + Suppress("```")
74
+
75
+ @classmethod
76
+ def start_token(cls):
77
+ return "<format>"
78
+
79
+ @classmethod
80
+ def end_token(cls):
81
+ return "</format>"
82
+
83
+
84
+ # Test cases
85
+ if __name__ == "__main__":
86
+ # Test formatting
87
+ code_file = CodeFileModel(
88
+ language="Python",
89
+ file_path="src/main.py",
90
+ code="def hello():\n print('Hello, World!')",
91
+ )
92
+ formatted = CodeFileModel.format(code_file)
93
+ expected_format = """<format>
94
+ code_file_model
95
+ src/main.py
96
+ ```Python
97
+ def hello():
98
+ print('Hello, World!')
99
+ ```
100
+ </format>"""
101
+ assert (
102
+ formatted == expected_format
103
+ ), f"Formatting failed. Expected:\n{expected_format}\nGot:\n{formatted}"
104
+ print("Formatting test passed.")
105
+
106
+ # Test parsing
107
+ parsed = CodeFileModel.parse(formatted)
108
+ assert (
109
+ parsed == code_file
110
+ ), f"Parsing failed. Expected:\n{code_file}\nGot:\n{parsed}"
111
+ print("Parsing test passed.")
112
+
113
+ # Test round-trip
114
+ round_trip = CodeFileModel.parse(CodeFileModel.format(code_file))
115
+ assert (
116
+ round_trip == code_file
117
+ ), f"Round-trip failed. Expected:\n{code_file}\nGot:\n{round_trip}"
118
+ print("Round-trip test passed.")
119
+
120
+ # Test with different values
121
+ code_file2 = CodeFileModel(
122
+ language="JavaScript",
123
+ file_path="src/app.js",
124
+ code="function greet() {\n console.log('Hello, World!');\n}",
125
+ )
126
+ formatted2 = CodeFileModel.format(code_file2)
127
+ parsed2 = CodeFileModel.parse(formatted2)
128
+ assert (
129
+ parsed2 == code_file2
130
+ ), f"Parsing failed for different values. Expected:\n{code_file2}\nGot:\n{parsed2}"
131
+ print("Different values test passed.")
132
+
133
+ print("All tests passed successfully!")
@@ -0,0 +1,121 @@
1
+ from abc import ABC, abstractmethod
2
+ from pydantic import BaseModel
3
+ from pyparsing import (
4
+ Word, alphas, alphanums, Suppress, OneOrMore,
5
+ LineEnd, SkipTo, ParseResults, Optional, Literal, White
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 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
+ spec = cls.parse_spec()
43
+ parsed = spec.parseString(content, parseAll=True)
44
+ return cls(**parsed.asDict())
45
+
46
+ class CodeFileModel(FormattingModel):
47
+ language: str
48
+ file_path: str
49
+ code: str
50
+
51
+ @classmethod
52
+ def format_spec(cls):
53
+ return "code_file_model\n{file_path}\n```{language}\n{code}\n```"
54
+
55
+ @classmethod
56
+ def parse_spec(cls):
57
+ header = Suppress("code_file_model") + LineEnd()
58
+ file_path = SkipTo(LineEnd()).setResultsName("file_path")
59
+ language = Suppress("```") + Word(alphas).setResultsName("language") + LineEnd()
60
+ code = SkipTo("```").setResultsName("code").setParseAction(lambda s, l, t: t[0].rstrip())
61
+
62
+ return (
63
+ header +
64
+ file_path +
65
+ language +
66
+ code +
67
+ Suppress("```")
68
+ )
69
+
70
+ @classmethod
71
+ def start_token(cls):
72
+ return '<format>'
73
+
74
+ @classmethod
75
+ def end_token(cls):
76
+ return '</format>'
77
+
78
+ # Test cases
79
+ if __name__ == "__main__":
80
+ # Test formatting
81
+ code_file = CodeFileModel(
82
+ language="Python",
83
+ file_path="src/main.py",
84
+ code="def hello():\n print('Hello, World!')"
85
+ )
86
+ formatted = CodeFileModel.format(code_file)
87
+ expected_format = """<format>
88
+ code_file_model
89
+ src/main.py
90
+ ```Python
91
+ def hello():
92
+ print('Hello, World!')
93
+ ```
94
+ </format>"""
95
+ assert formatted == expected_format, f"Formatting failed. Expected:\n{expected_format}\nGot:\n{formatted}"
96
+ print("Formatting test passed.")
97
+
98
+ # Test parsing
99
+ parsed = CodeFileModel.parse(formatted)
100
+ assert parsed == code_file, f"Parsing failed. Expected:\n{code_file}\nGot:\n{parsed}"
101
+ print("Parsing test passed.")
102
+
103
+ # Test round-trip
104
+ round_trip = CodeFileModel.parse(CodeFileModel.format(code_file))
105
+ assert round_trip == code_file, f"Round-trip failed. Expected:\n{code_file}\nGot:\n{round_trip}"
106
+ print("Round-trip test passed.")
107
+
108
+ # Test with different values
109
+ code_file2 = CodeFileModel(
110
+ language="JavaScript",
111
+ file_path="src/app.js",
112
+ code="function greet() {\n console.log('Hello, World!');\n}"
113
+ )
114
+ formatted2 = CodeFileModel.format(code_file2)
115
+ parsed2 = CodeFileModel.parse(formatted2)
116
+ assert parsed2 == code_file2, f"Parsing failed for different values. Expected:\n{code_file2}\nGot:\n{parsed2}"
117
+ print("Different values test passed.")
118
+
119
+ print("All tests passed successfully!")
120
+
121
+