jaclang 0.7.14__py3-none-any.whl → 0.7.17__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.
Potentially problematic release.
This version of jaclang might be problematic. Click here for more details.
- jaclang/cli/cli.py +147 -77
- jaclang/cli/cmdreg.py +9 -12
- jaclang/compiler/__init__.py +19 -53
- jaclang/compiler/absyntree.py +94 -16
- jaclang/compiler/constant.py +8 -8
- jaclang/compiler/jac.lark +4 -3
- jaclang/compiler/parser.py +41 -25
- jaclang/compiler/passes/ir_pass.py +4 -13
- jaclang/compiler/passes/main/__init__.py +1 -1
- jaclang/compiler/passes/main/access_modifier_pass.py +96 -147
- jaclang/compiler/passes/main/fuse_typeinfo_pass.py +155 -54
- jaclang/compiler/passes/main/import_pass.py +99 -75
- jaclang/compiler/passes/main/py_collect_dep_pass.py +70 -0
- jaclang/compiler/passes/main/pyast_gen_pass.py +328 -565
- jaclang/compiler/passes/main/pyast_load_pass.py +33 -6
- jaclang/compiler/passes/main/pyjac_ast_link_pass.py +7 -0
- jaclang/compiler/passes/main/registry_pass.py +37 -3
- jaclang/compiler/passes/main/schedules.py +9 -2
- jaclang/compiler/passes/main/sym_tab_build_pass.py +10 -6
- jaclang/compiler/passes/main/tests/__init__.py +1 -1
- jaclang/compiler/passes/main/tests/fixtures/autoimpl.empty.impl.jac +0 -0
- jaclang/compiler/passes/main/tests/fixtures/autoimpl.jac +1 -1
- jaclang/compiler/passes/main/tests/fixtures/py_imp_test.jac +29 -0
- jaclang/compiler/passes/main/tests/fixtures/pygame_mock/__init__.py +3 -0
- jaclang/compiler/passes/main/tests/fixtures/pygame_mock/color.py +3 -0
- jaclang/compiler/passes/main/tests/fixtures/pygame_mock/constants.py +5 -0
- jaclang/compiler/passes/main/tests/fixtures/pygame_mock/display.py +2 -0
- jaclang/compiler/passes/main/tests/test_import_pass.py +72 -13
- jaclang/compiler/passes/main/type_check_pass.py +22 -5
- jaclang/compiler/passes/tool/jac_formatter_pass.py +135 -89
- jaclang/compiler/passes/tool/tests/fixtures/corelib.jac +37 -41
- jaclang/compiler/passes/tool/tests/fixtures/corelib_fmt.jac +37 -42
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/access_mod_check.jac +27 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/architype_test.jac +13 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/comment_alignment.jac +11 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/comments.jac +13 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/decorator_stack.jac +37 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/esc_keywords.jac +5 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/long_names.jac +19 -0
- jaclang/compiler/passes/tool/tests/fixtures/general_format_checks/triple_quoted_string.jac +6 -0
- jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +11 -0
- jaclang/compiler/passes/tool/tests/test_unparse_validate.py +33 -39
- jaclang/compiler/passes/transform.py +4 -0
- jaclang/compiler/passes/utils/mypy_ast_build.py +45 -0
- jaclang/compiler/semtable.py +31 -7
- jaclang/compiler/symtable.py +16 -11
- jaclang/compiler/tests/test_importer.py +25 -10
- jaclang/langserve/engine.py +104 -118
- jaclang/langserve/sem_manager.py +379 -0
- jaclang/langserve/server.py +24 -11
- jaclang/langserve/tests/fixtures/base_module_structure.jac +27 -6
- jaclang/langserve/tests/fixtures/circle.jac +3 -3
- jaclang/langserve/tests/fixtures/circle_err.jac +3 -3
- jaclang/langserve/tests/fixtures/circle_pure.test.jac +3 -3
- jaclang/langserve/tests/fixtures/import_include_statements.jac +1 -1
- jaclang/langserve/tests/fixtures/rename.jac +30 -0
- jaclang/langserve/tests/test_sem_tokens.py +277 -0
- jaclang/langserve/tests/test_server.py +287 -17
- jaclang/langserve/utils.py +184 -98
- jaclang/plugin/builtin.py +1 -1
- jaclang/plugin/default.py +288 -92
- jaclang/plugin/feature.py +65 -27
- jaclang/plugin/spec.py +62 -23
- jaclang/plugin/tests/fixtures/other_root_access.jac +82 -0
- jaclang/plugin/tests/test_jaseci.py +414 -42
- jaclang/runtimelib/architype.py +650 -0
- jaclang/{core → runtimelib}/constructs.py +5 -8
- jaclang/{core → runtimelib}/context.py +86 -59
- jaclang/runtimelib/importer.py +361 -0
- jaclang/runtimelib/machine.py +158 -0
- jaclang/runtimelib/memory.py +158 -0
- jaclang/{core → runtimelib}/utils.py +30 -15
- jaclang/settings.py +5 -4
- jaclang/tests/fixtures/abc.jac +3 -3
- jaclang/tests/fixtures/access_checker.jac +12 -17
- jaclang/tests/fixtures/access_modifier.jac +88 -33
- jaclang/tests/fixtures/baddy.jac +3 -0
- jaclang/tests/fixtures/baddy.test.jac +3 -0
- jaclang/tests/fixtures/bar.jac +34 -0
- jaclang/tests/fixtures/byllmissue.jac +1 -5
- jaclang/tests/fixtures/chandra_bugs2.jac +11 -10
- jaclang/tests/fixtures/cls_method.jac +41 -0
- jaclang/tests/fixtures/dblhello.jac +6 -0
- jaclang/tests/fixtures/deep/one_lev.jac +3 -3
- jaclang/tests/fixtures/deep/one_lev_dup.jac +2 -3
- jaclang/tests/fixtures/deep_import_mods.jac +13 -0
- jaclang/tests/fixtures/edge_node_walk.jac +1 -1
- jaclang/tests/fixtures/edge_ops.jac +1 -1
- jaclang/tests/fixtures/edges_walk.jac +1 -1
- jaclang/tests/fixtures/err.impl.jac +3 -0
- jaclang/tests/fixtures/err.jac +4 -2
- jaclang/tests/fixtures/err_runtime.jac +15 -0
- jaclang/tests/fixtures/foo.jac +43 -0
- jaclang/tests/fixtures/gendot_bubble_sort.jac +1 -1
- jaclang/tests/fixtures/hello.jac +4 -0
- jaclang/tests/fixtures/impl_grab.impl.jac +2 -1
- jaclang/tests/fixtures/impl_grab.jac +4 -1
- jaclang/tests/fixtures/import.jac +9 -0
- jaclang/tests/fixtures/index_slice.jac +30 -0
- jaclang/tests/fixtures/jp_importer_auto.jac +14 -0
- jaclang/tests/fixtures/maxfail_run_test.jac +4 -4
- jaclang/tests/fixtures/needs_import.jac +2 -2
- jaclang/tests/fixtures/pyfunc_1.py +1 -1
- jaclang/tests/fixtures/pyfunc_2.py +5 -2
- jaclang/tests/fixtures/pygame_mock/__init__.py +3 -0
- jaclang/tests/fixtures/pygame_mock/color.py +3 -0
- jaclang/tests/fixtures/pygame_mock/constants.py +5 -0
- jaclang/tests/fixtures/pygame_mock/display.py +2 -0
- jaclang/tests/fixtures/pygame_mock/inner/__init__.py +0 -0
- jaclang/tests/fixtures/pygame_mock/inner/iner_mod.py +2 -0
- jaclang/tests/fixtures/registry.jac +9 -0
- jaclang/tests/fixtures/run_test.jac +4 -4
- jaclang/tests/fixtures/semstr.jac +1 -4
- jaclang/tests/fixtures/simple_archs.jac +1 -1
- jaclang/tests/test_cli.py +109 -3
- jaclang/tests/test_language.py +170 -68
- jaclang/tests/test_reference.py +2 -3
- jaclang/utils/helpers.py +45 -21
- jaclang/utils/test.py +9 -0
- jaclang/utils/treeprinter.py +30 -7
- {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/METADATA +3 -2
- {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/RECORD +126 -90
- jaclang/core/architype.py +0 -502
- jaclang/core/importer.py +0 -344
- jaclang/core/memory.py +0 -99
- jaclang/tests/fixtures/aott_raise.jac +0 -25
- jaclang/tests/fixtures/package_import.jac +0 -6
- /jaclang/{core → runtimelib}/__init__.py +0 -0
- /jaclang/{core → runtimelib}/test.py +0 -0
- {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/WHEEL +0 -0
- {jaclang-0.7.14.dist-info → jaclang-0.7.17.dist-info}/entry_points.txt +0 -0
jaclang/tests/test_language.py
CHANGED
|
@@ -12,8 +12,8 @@ from jaclang import jac_import
|
|
|
12
12
|
from jaclang.cli import cli
|
|
13
13
|
from jaclang.compiler.compile import jac_file_to_pass, jac_pass_to_pass, jac_str_to_pass
|
|
14
14
|
from jaclang.compiler.passes.main.schedules import py_code_gen_typed
|
|
15
|
-
from jaclang.
|
|
16
|
-
from jaclang.
|
|
15
|
+
from jaclang.runtimelib.context import SUPER_ROOT_ANCHOR
|
|
16
|
+
from jaclang.runtimelib.machine import JacMachine, JacProgram
|
|
17
17
|
from jaclang.utils.test import TestCase
|
|
18
18
|
|
|
19
19
|
|
|
@@ -22,8 +22,17 @@ class JacLanguageTests(TestCase):
|
|
|
22
22
|
|
|
23
23
|
def setUp(self) -> None:
|
|
24
24
|
"""Set up test."""
|
|
25
|
+
SUPER_ROOT_ANCHOR.edges.clear()
|
|
26
|
+
JacMachine(self.fixture_abs_path("./")).attach_program(
|
|
27
|
+
JacProgram(mod_bundle=None, bytecode=None)
|
|
28
|
+
)
|
|
25
29
|
return super().setUp()
|
|
26
30
|
|
|
31
|
+
def tearDown(self) -> None:
|
|
32
|
+
"""Tear down test."""
|
|
33
|
+
JacMachine.detach()
|
|
34
|
+
return super().tearDown()
|
|
35
|
+
|
|
27
36
|
def test_sub_abilities(self) -> None:
|
|
28
37
|
"""Basic test for pass."""
|
|
29
38
|
captured_output = io.StringIO()
|
|
@@ -106,13 +115,12 @@ class JacLanguageTests(TestCase):
|
|
|
106
115
|
stdout_value,
|
|
107
116
|
"{'apple': None, 'pineapple': None}\n"
|
|
108
117
|
"This is a long\n"
|
|
109
|
-
"
|
|
118
|
+
" line of code.\n"
|
|
110
119
|
"{'a': 'apple', 'b': 'ball', 'c': 'cat', 'd': 'dog', 'e': 'elephant'}\n",
|
|
111
120
|
)
|
|
112
121
|
|
|
113
122
|
def test_ignore(self) -> None:
|
|
114
123
|
"""Parse micro jac file."""
|
|
115
|
-
Jac.get_root()._jac_.edges.clear()
|
|
116
124
|
captured_output = io.StringIO()
|
|
117
125
|
sys.stdout = captured_output
|
|
118
126
|
jac_import("ignore_dup", base_path=self.fixture_abs_path("./"))
|
|
@@ -206,17 +214,34 @@ class JacLanguageTests(TestCase):
|
|
|
206
214
|
|
|
207
215
|
def test_deep_imports(self) -> None:
|
|
208
216
|
"""Parse micro jac file."""
|
|
209
|
-
Jac.get_root()._jac_.edges.clear()
|
|
210
217
|
captured_output = io.StringIO()
|
|
211
218
|
sys.stdout = captured_output
|
|
219
|
+
|
|
212
220
|
jac_import("deep_import", base_path=self.fixture_abs_path("./"))
|
|
213
221
|
sys.stdout = sys.__stdout__
|
|
214
222
|
stdout_value = captured_output.getvalue()
|
|
215
223
|
self.assertEqual(stdout_value.split("\n")[0], "one level deeperslHello World!")
|
|
216
224
|
|
|
225
|
+
def test_deep_imports_mods(self) -> None:
|
|
226
|
+
"""Parse micro jac file."""
|
|
227
|
+
targets = [
|
|
228
|
+
"deep",
|
|
229
|
+
"deep.deeper",
|
|
230
|
+
"deep.mycode",
|
|
231
|
+
"deep.deeper.snd_lev",
|
|
232
|
+
"deep.one_lev",
|
|
233
|
+
]
|
|
234
|
+
for i in targets:
|
|
235
|
+
if i in sys.modules:
|
|
236
|
+
del sys.modules[i]
|
|
237
|
+
jac_import("deep_import_mods", base_path=self.fixture_abs_path("./"))
|
|
238
|
+
mods = JacMachine.get().loaded_modules.keys()
|
|
239
|
+
for i in targets:
|
|
240
|
+
self.assertIn(i, mods)
|
|
241
|
+
self.assertEqual(len([i for i in mods if i.startswith("deep")]), 6)
|
|
242
|
+
|
|
217
243
|
def test_deep_outer_imports_one(self) -> None:
|
|
218
244
|
"""Parse micro jac file."""
|
|
219
|
-
Jac.get_root()._jac_.edges.clear()
|
|
220
245
|
captured_output = io.StringIO()
|
|
221
246
|
sys.stdout = captured_output
|
|
222
247
|
jac_import(
|
|
@@ -229,7 +254,6 @@ class JacLanguageTests(TestCase):
|
|
|
229
254
|
|
|
230
255
|
def test_deep_outer_imports_from_loc(self) -> None:
|
|
231
256
|
"""Parse micro jac file."""
|
|
232
|
-
Jac.get_root()._jac_.edges.clear()
|
|
233
257
|
captured_output = io.StringIO()
|
|
234
258
|
sys.stdout = captured_output
|
|
235
259
|
os.chdir(self.fixture_abs_path("./deep/deeper/"))
|
|
@@ -241,7 +265,6 @@ class JacLanguageTests(TestCase):
|
|
|
241
265
|
|
|
242
266
|
# def test_second_deep_outer_imports(self) -> None:
|
|
243
267
|
# """Parse micro jac file."""
|
|
244
|
-
# Jac.get_root()._jac_.edges.clear()
|
|
245
268
|
# captured_output = io.StringIO()
|
|
246
269
|
# sys.stdout = captured_output
|
|
247
270
|
# jac_import(
|
|
@@ -254,7 +277,6 @@ class JacLanguageTests(TestCase):
|
|
|
254
277
|
|
|
255
278
|
def test_has_lambda_goodness(self) -> None:
|
|
256
279
|
"""Test has lambda_goodness."""
|
|
257
|
-
Jac.get_root()._jac_.edges.clear()
|
|
258
280
|
captured_output = io.StringIO()
|
|
259
281
|
sys.stdout = captured_output
|
|
260
282
|
jac_import("has_goodness", base_path=self.fixture_abs_path("./"))
|
|
@@ -265,7 +287,6 @@ class JacLanguageTests(TestCase):
|
|
|
265
287
|
|
|
266
288
|
def test_conn_assign_on_edges(self) -> None:
|
|
267
289
|
"""Test conn assign on edges."""
|
|
268
|
-
Jac.get_root()._jac_.edges.clear()
|
|
269
290
|
captured_output = io.StringIO()
|
|
270
291
|
sys.stdout = captured_output
|
|
271
292
|
jac_import("edge_ops", base_path=self.fixture_abs_path("./"))
|
|
@@ -277,7 +298,6 @@ class JacLanguageTests(TestCase):
|
|
|
277
298
|
|
|
278
299
|
def test_disconnect(self) -> None:
|
|
279
300
|
"""Test conn assign on edges."""
|
|
280
|
-
Jac.get_root()._jac_.edges.clear()
|
|
281
301
|
captured_output = io.StringIO()
|
|
282
302
|
sys.stdout = captured_output
|
|
283
303
|
jac_import("disconn", base_path=self.fixture_abs_path("./"))
|
|
@@ -295,7 +315,6 @@ class JacLanguageTests(TestCase):
|
|
|
295
315
|
|
|
296
316
|
def test_simple_archs(self) -> None:
|
|
297
317
|
"""Test conn assign on edges."""
|
|
298
|
-
Jac.get_root()._jac_.edges.clear()
|
|
299
318
|
captured_output = io.StringIO()
|
|
300
319
|
sys.stdout = captured_output
|
|
301
320
|
jac_import("simple_archs", base_path=self.fixture_abs_path("./"))
|
|
@@ -306,7 +325,6 @@ class JacLanguageTests(TestCase):
|
|
|
306
325
|
|
|
307
326
|
def test_edge_walk(self) -> None:
|
|
308
327
|
"""Test walking through edges."""
|
|
309
|
-
Jac.get_root()._jac_.edges.clear()
|
|
310
328
|
captured_output = io.StringIO()
|
|
311
329
|
sys.stdout = captured_output
|
|
312
330
|
jac_import("edges_walk", base_path=self.fixture_abs_path("./"))
|
|
@@ -320,7 +338,6 @@ class JacLanguageTests(TestCase):
|
|
|
320
338
|
|
|
321
339
|
def test_impl_grab(self) -> None:
|
|
322
340
|
"""Test walking through edges."""
|
|
323
|
-
Jac.get_root()._jac_.edges.clear()
|
|
324
341
|
captured_output = io.StringIO()
|
|
325
342
|
sys.stdout = captured_output
|
|
326
343
|
jac_import("impl_grab", base_path=self.fixture_abs_path("./"))
|
|
@@ -330,7 +347,6 @@ class JacLanguageTests(TestCase):
|
|
|
330
347
|
|
|
331
348
|
def test_tuple_of_tuple_assign(self) -> None:
|
|
332
349
|
"""Test walking through edges."""
|
|
333
|
-
Jac.get_root()._jac_.edges.clear()
|
|
334
350
|
captured_output = io.StringIO()
|
|
335
351
|
sys.stdout = captured_output
|
|
336
352
|
jac_import("tuplytuples", base_path=self.fixture_abs_path("./"))
|
|
@@ -343,7 +359,6 @@ class JacLanguageTests(TestCase):
|
|
|
343
359
|
|
|
344
360
|
def test_deferred_field(self) -> None:
|
|
345
361
|
"""Test walking through edges."""
|
|
346
|
-
Jac.get_root()._jac_.edges.clear()
|
|
347
362
|
captured_output = io.StringIO()
|
|
348
363
|
sys.stdout = captured_output
|
|
349
364
|
jac_import("deferred_field", base_path=self.fixture_abs_path("./"))
|
|
@@ -356,18 +371,15 @@ class JacLanguageTests(TestCase):
|
|
|
356
371
|
|
|
357
372
|
def test_gen_dot_builtin(self) -> None:
|
|
358
373
|
"""Test the dot gen of nodes and edges as a builtin."""
|
|
359
|
-
Jac.get_root()._jac_.edges.clear()
|
|
360
374
|
captured_output = io.StringIO()
|
|
361
375
|
sys.stdout = captured_output
|
|
362
376
|
jac_import("builtin_dotgen", base_path=self.fixture_abs_path("./"))
|
|
363
377
|
sys.stdout = sys.__stdout__
|
|
364
378
|
stdout_value = captured_output.getvalue()
|
|
365
|
-
print(stdout_value)
|
|
366
379
|
self.assertEqual(stdout_value.count("True"), 14)
|
|
367
380
|
|
|
368
381
|
def test_with_contexts(self) -> None:
|
|
369
382
|
"""Test walking through edges."""
|
|
370
|
-
Jac.get_root()._jac_.edges.clear()
|
|
371
383
|
captured_output = io.StringIO()
|
|
372
384
|
sys.stdout = captured_output
|
|
373
385
|
jac_import("with_context", base_path=self.fixture_abs_path("./"))
|
|
@@ -385,10 +397,7 @@ class JacLanguageTests(TestCase):
|
|
|
385
397
|
"""Parse micro jac file."""
|
|
386
398
|
captured_output = io.StringIO()
|
|
387
399
|
sys.stdout = captured_output
|
|
388
|
-
jac_import(
|
|
389
|
-
"micro.typed_filter_compr",
|
|
390
|
-
base_path=self.examples_abs_path(""),
|
|
391
|
-
)
|
|
400
|
+
jac_import("micro.typed_filter_compr", base_path=self.examples_abs_path(""))
|
|
392
401
|
sys.stdout = sys.__stdout__
|
|
393
402
|
stdout_value = captured_output.getvalue()
|
|
394
403
|
self.assertIn(
|
|
@@ -400,7 +409,6 @@ class JacLanguageTests(TestCase):
|
|
|
400
409
|
|
|
401
410
|
def test_edge_node_walk(self) -> None:
|
|
402
411
|
"""Test walking through edges and nodes."""
|
|
403
|
-
Jac.get_root()._jac_.edges.clear()
|
|
404
412
|
captured_output = io.StringIO()
|
|
405
413
|
sys.stdout = captured_output
|
|
406
414
|
jac_import("edge_node_walk", base_path=self.fixture_abs_path("./"))
|
|
@@ -414,14 +422,12 @@ class JacLanguageTests(TestCase):
|
|
|
414
422
|
|
|
415
423
|
def test_annotation_tuple_issue(self) -> None:
|
|
416
424
|
"""Test conn assign on edges."""
|
|
417
|
-
Jac.get_root()._jac_.edges.clear()
|
|
418
425
|
mypass = jac_file_to_pass(self.fixture_abs_path("./slice_vals.jac"))
|
|
419
426
|
self.assertIn("Annotated[Str, INT, BLAH]", mypass.ir.gen.py)
|
|
420
427
|
self.assertIn("tuple[int, Optional[type], Optional[tuple]]", mypass.ir.gen.py)
|
|
421
428
|
|
|
422
429
|
def test_impl_decl_resolution_fix(self) -> None:
|
|
423
430
|
"""Test walking through edges and nodes."""
|
|
424
|
-
Jac.get_root()._jac_.edges.clear()
|
|
425
431
|
captured_output = io.StringIO()
|
|
426
432
|
sys.stdout = captured_output
|
|
427
433
|
jac_import("mtest", base_path=self.fixture_abs_path("./"))
|
|
@@ -446,9 +452,11 @@ class JacLanguageTests(TestCase):
|
|
|
446
452
|
) as f:
|
|
447
453
|
registry = pickle.load(f)
|
|
448
454
|
|
|
449
|
-
self.assertEqual(len(registry.registry),
|
|
450
|
-
self.assertEqual(len(list(registry.registry.items())[0][1]),
|
|
451
|
-
self.assertEqual(list(registry.registry.items())[
|
|
455
|
+
self.assertEqual(len(registry.registry), 9)
|
|
456
|
+
self.assertEqual(len(list(registry.registry.items())[0][1]), 2)
|
|
457
|
+
self.assertEqual(list(registry.registry.items())[3][0].scope, "Person")
|
|
458
|
+
_, sem_info = registry.lookup(name="normal_ability")
|
|
459
|
+
self.assertEqual(len(sem_info.get_children(registry)), 2)
|
|
452
460
|
|
|
453
461
|
def test_enum_inside_arch(self) -> None:
|
|
454
462
|
"""Test Enum as member stmt."""
|
|
@@ -461,12 +469,23 @@ class JacLanguageTests(TestCase):
|
|
|
461
469
|
|
|
462
470
|
def test_needs_import_1(self) -> None:
|
|
463
471
|
"""Test py ast to Jac ast conversion output."""
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
from jaclang.compiler.passes.main.schedules import
|
|
472
|
+
file_name = self.fixture_abs_path("pyfunc_1.py")
|
|
473
|
+
|
|
474
|
+
from jaclang.compiler.passes.main.schedules import py_code_gen_typed
|
|
475
|
+
from jaclang.compiler.passes.main.pyast_load_pass import PyastBuildPass
|
|
476
|
+
import ast as py_ast
|
|
467
477
|
import jaclang.compiler.absyntree as ast
|
|
468
478
|
|
|
469
|
-
|
|
479
|
+
with open(file_name, "r") as f:
|
|
480
|
+
parsed_ast = py_ast.parse(f.read())
|
|
481
|
+
try:
|
|
482
|
+
py_ast_build_pass = PyastBuildPass(
|
|
483
|
+
input_ir=ast.PythonModuleAst(parsed_ast, mod_path=file_name),
|
|
484
|
+
)
|
|
485
|
+
except Exception as e:
|
|
486
|
+
return f"Error While Jac to Py AST conversion: {e}"
|
|
487
|
+
|
|
488
|
+
ir = jac_pass_to_pass(py_ast_build_pass, schedule=py_code_gen_typed).ir
|
|
470
489
|
self.assertEqual(len(ir.get_all_sub_nodes(ast.Architype)), 7)
|
|
471
490
|
captured_output = io.StringIO()
|
|
472
491
|
sys.stdout = captured_output
|
|
@@ -474,7 +493,6 @@ class JacLanguageTests(TestCase):
|
|
|
474
493
|
sys.stdout = sys.__stdout__
|
|
475
494
|
stdout_value = captured_output.getvalue()
|
|
476
495
|
self.assertIn("pyfunc_1 imported", stdout_value)
|
|
477
|
-
settings.py_raise = False
|
|
478
496
|
|
|
479
497
|
def test_pyfunc_1(self) -> None:
|
|
480
498
|
"""Test py ast to Jac ast conversion."""
|
|
@@ -509,13 +527,26 @@ class JacLanguageTests(TestCase):
|
|
|
509
527
|
|
|
510
528
|
def test_needs_import_2(self) -> None:
|
|
511
529
|
"""Test py ast to Jac ast conversion output."""
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
from jaclang.compiler.passes.main.schedules import
|
|
530
|
+
file_name = self.fixture_abs_path("pyfunc_2.py")
|
|
531
|
+
|
|
532
|
+
from jaclang.compiler.passes.main.schedules import py_code_gen_typed
|
|
533
|
+
from jaclang.compiler.passes.main.pyast_load_pass import PyastBuildPass
|
|
534
|
+
import ast as py_ast
|
|
515
535
|
import jaclang.compiler.absyntree as ast
|
|
516
536
|
|
|
517
|
-
|
|
518
|
-
|
|
537
|
+
with open(file_name, "r") as f:
|
|
538
|
+
parsed_ast = py_ast.parse(f.read())
|
|
539
|
+
try:
|
|
540
|
+
py_ast_build_pass = PyastBuildPass(
|
|
541
|
+
input_ir=ast.PythonModuleAst(parsed_ast, mod_path=file_name),
|
|
542
|
+
)
|
|
543
|
+
except Exception as e:
|
|
544
|
+
return f"Error While Jac to Py AST conversion: {e}"
|
|
545
|
+
|
|
546
|
+
ir = jac_pass_to_pass(py_ast_build_pass, schedule=py_code_gen_typed).ir
|
|
547
|
+
self.assertEqual(
|
|
548
|
+
len(ir.get_all_sub_nodes(ast.Architype)), 8
|
|
549
|
+
) # Because of the Architype from math
|
|
519
550
|
captured_output = io.StringIO()
|
|
520
551
|
sys.stdout = captured_output
|
|
521
552
|
jac_import("needs_import_2", base_path=self.fixture_abs_path("./"))
|
|
@@ -523,7 +554,6 @@ class JacLanguageTests(TestCase):
|
|
|
523
554
|
stdout_value = captured_output.getvalue()
|
|
524
555
|
self.assertIn("pyfunc_2 imported", stdout_value)
|
|
525
556
|
self.assertEqual(stdout_value.count("<class 'bytes'>"), 3)
|
|
526
|
-
settings.py_raise = False
|
|
527
557
|
|
|
528
558
|
def test_pyfunc_2(self) -> None:
|
|
529
559
|
"""Test py ast to Jac ast conversion."""
|
|
@@ -541,23 +571,36 @@ class JacLanguageTests(TestCase):
|
|
|
541
571
|
self.assertIn("class X {\n with entry {\n a_b = 67;", output)
|
|
542
572
|
self.assertIn("br = b'Hello\\\\\\\\nWorld'", output)
|
|
543
573
|
self.assertIn("class Circle {\n can init(radius: float", output)
|
|
574
|
+
self.assertIn("<>node = 90; \n print(<>node) ;\n}\n", output)
|
|
544
575
|
|
|
545
576
|
def test_needs_import_3(self) -> None:
|
|
546
577
|
"""Test py ast to Jac ast conversion output."""
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
from jaclang.compiler.passes.main.schedules import
|
|
578
|
+
file_name = self.fixture_abs_path("pyfunc_3.py")
|
|
579
|
+
|
|
580
|
+
from jaclang.compiler.passes.main.schedules import py_code_gen_typed
|
|
581
|
+
from jaclang.compiler.passes.main.pyast_load_pass import PyastBuildPass
|
|
582
|
+
import ast as py_ast
|
|
550
583
|
import jaclang.compiler.absyntree as ast
|
|
551
584
|
|
|
552
|
-
|
|
553
|
-
|
|
585
|
+
with open(file_name, "r") as f:
|
|
586
|
+
parsed_ast = py_ast.parse(f.read())
|
|
587
|
+
try:
|
|
588
|
+
py_ast_build_pass = PyastBuildPass(
|
|
589
|
+
input_ir=ast.PythonModuleAst(parsed_ast, mod_path=file_name),
|
|
590
|
+
)
|
|
591
|
+
except Exception as e:
|
|
592
|
+
return f"Error While Jac to Py AST conversion: {e}"
|
|
593
|
+
|
|
594
|
+
ir = jac_pass_to_pass(py_ast_build_pass, schedule=py_code_gen_typed).ir
|
|
595
|
+
self.assertEqual(
|
|
596
|
+
len(ir.get_all_sub_nodes(ast.Architype)), 38
|
|
597
|
+
) # Because of the Architype from other imports
|
|
554
598
|
captured_output = io.StringIO()
|
|
555
599
|
sys.stdout = captured_output
|
|
556
600
|
jac_import("needs_import_3", base_path=self.fixture_abs_path("./"))
|
|
557
601
|
sys.stdout = sys.__stdout__
|
|
558
602
|
stdout_value = captured_output.getvalue()
|
|
559
603
|
self.assertIn("pyfunc_3 imported", stdout_value)
|
|
560
|
-
settings.py_raise = False
|
|
561
604
|
|
|
562
605
|
def test_pyfunc_3(self) -> None:
|
|
563
606
|
"""Test py ast to Jac ast conversion."""
|
|
@@ -672,18 +715,17 @@ class JacLanguageTests(TestCase):
|
|
|
672
715
|
|
|
673
716
|
def test_random_check(self) -> None:
|
|
674
717
|
"""Test py ast to Jac ast conversion output."""
|
|
675
|
-
settings.py_raise = True
|
|
676
|
-
|
|
677
718
|
from jaclang.compiler.passes.main import PyastBuildPass
|
|
678
719
|
import jaclang.compiler.absyntree as ast
|
|
679
720
|
import ast as py_ast
|
|
721
|
+
from jaclang.settings import settings
|
|
680
722
|
|
|
681
|
-
module_paths = ["random", "
|
|
723
|
+
module_paths = ["random", "ast"]
|
|
682
724
|
for module_path in module_paths:
|
|
683
725
|
stdlib_dir = sysconfig.get_paths()["stdlib"]
|
|
684
726
|
file_path = os.path.join(
|
|
685
727
|
stdlib_dir,
|
|
686
|
-
module_path +
|
|
728
|
+
module_path + ".py",
|
|
687
729
|
)
|
|
688
730
|
with open(file_path) as f:
|
|
689
731
|
jac_ast = PyastBuildPass(
|
|
@@ -691,23 +733,21 @@ class JacLanguageTests(TestCase):
|
|
|
691
733
|
py_ast.parse(f.read()), mod_path=file_path
|
|
692
734
|
)
|
|
693
735
|
)
|
|
736
|
+
settings.print_py_raised_ast = True
|
|
694
737
|
ir = jac_pass_to_pass(jac_ast).ir
|
|
695
738
|
gen_ast = ir.pp()
|
|
696
739
|
if module_path == "random":
|
|
697
740
|
self.assertIn("ModulePath - statistics -", gen_ast)
|
|
698
741
|
else:
|
|
699
|
-
self.assertIn("+-- Name -
|
|
700
|
-
settings.py_raise = False
|
|
742
|
+
self.assertIn("+-- Name - NodeTransformer - Type: No", gen_ast)
|
|
701
743
|
|
|
702
744
|
def test_deep_py_load_imports(self) -> None: # we can get rid of this, isn't?
|
|
703
745
|
"""Test py ast to Jac ast conversion output."""
|
|
704
|
-
settings.py_raise = True
|
|
705
746
|
file_name = os.path.join(self.fixture_abs_path("./"), "random_check.jac")
|
|
706
747
|
from jaclang.compiler.passes.main.schedules import py_code_gen, PyImportPass
|
|
707
748
|
|
|
708
749
|
imp = jac_file_to_pass(file_name, schedule=py_code_gen, target=PyImportPass)
|
|
709
750
|
self.assertEqual(len(imp.import_table), 1)
|
|
710
|
-
settings.py_raise = False
|
|
711
751
|
|
|
712
752
|
def test_access_modifier(self) -> None:
|
|
713
753
|
"""Test for access tags working."""
|
|
@@ -719,29 +759,38 @@ class JacLanguageTests(TestCase):
|
|
|
719
759
|
)
|
|
720
760
|
sys.stdout = sys.__stdout__
|
|
721
761
|
stdout_value = captured_output.getvalue()
|
|
722
|
-
self.
|
|
723
|
-
self.assertIn('Can not access private variable "privmethod"', stdout_value)
|
|
724
|
-
self.assertIn('Can not access private variable "BankAccount"', stdout_value)
|
|
725
|
-
self.assertNotIn(" Name: ", stdout_value)
|
|
762
|
+
self.assertEqual(stdout_value.count("Invalid access"), 18)
|
|
726
763
|
|
|
727
764
|
def test_deep_convert(self) -> None:
|
|
728
765
|
"""Test py ast to Jac ast conversion output."""
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
from jaclang.compiler.passes.main.schedules import
|
|
766
|
+
file_name = self.fixture_abs_path("pyfunc_1.py")
|
|
767
|
+
|
|
768
|
+
from jaclang.compiler.passes.main.schedules import py_code_gen_typed
|
|
769
|
+
from jaclang.compiler.passes.main.pyast_load_pass import PyastBuildPass
|
|
770
|
+
import ast as py_ast
|
|
732
771
|
import jaclang.compiler.absyntree as ast
|
|
772
|
+
from jaclang.settings import settings
|
|
773
|
+
|
|
774
|
+
with open(file_name, "r") as f:
|
|
775
|
+
parsed_ast = py_ast.parse(f.read())
|
|
776
|
+
try:
|
|
777
|
+
py_ast_build_pass = PyastBuildPass(
|
|
778
|
+
input_ir=ast.PythonModuleAst(parsed_ast, mod_path=file_name),
|
|
779
|
+
)
|
|
780
|
+
except Exception as e:
|
|
781
|
+
return f"Error While Jac to Py AST conversion: {e}"
|
|
733
782
|
|
|
734
|
-
|
|
783
|
+
settings.print_py_raised_ast = True
|
|
784
|
+
ir = jac_pass_to_pass(py_ast_build_pass, schedule=py_code_gen_typed).ir
|
|
735
785
|
jac_ast = ir.pp()
|
|
736
786
|
self.assertIn(' | +-- String - "Loop compl', jac_ast)
|
|
737
|
-
self.assertEqual(len(ir.get_all_sub_nodes(ast.SubNodeList)),
|
|
787
|
+
self.assertEqual(len(ir.get_all_sub_nodes(ast.SubNodeList)), 269)
|
|
738
788
|
captured_output = io.StringIO()
|
|
739
789
|
sys.stdout = captured_output
|
|
740
790
|
jac_import("deep_convert", base_path=self.fixture_abs_path("./"))
|
|
741
791
|
sys.stdout = sys.__stdout__
|
|
742
792
|
stdout_value = captured_output.getvalue()
|
|
743
793
|
self.assertIn("Deep convo is imported", stdout_value)
|
|
744
|
-
settings.py_raise = settings.py_raise_deep = False
|
|
745
794
|
|
|
746
795
|
def test_override_walker_inherit(self) -> None:
|
|
747
796
|
"""Test py ast to Jac ast conversion output."""
|
|
@@ -754,7 +803,6 @@ class JacLanguageTests(TestCase):
|
|
|
754
803
|
|
|
755
804
|
def test_ds_type_check_pass(self) -> None:
|
|
756
805
|
"""Test conn assign on edges."""
|
|
757
|
-
Jac.get_root()._jac_.edges.clear()
|
|
758
806
|
mypass = jac_file_to_pass(
|
|
759
807
|
self.examples_abs_path("micro/simple_walk.jac"),
|
|
760
808
|
schedule=py_code_gen_typed,
|
|
@@ -764,7 +812,6 @@ class JacLanguageTests(TestCase):
|
|
|
764
812
|
|
|
765
813
|
def test_ds_type_check_pass2(self) -> None:
|
|
766
814
|
"""Test conn assign on edges."""
|
|
767
|
-
Jac.get_root()._jac_.edges.clear()
|
|
768
815
|
mypass = jac_file_to_pass(
|
|
769
816
|
self.examples_abs_path("guess_game/guess_game5.jac"),
|
|
770
817
|
schedule=py_code_gen_typed,
|
|
@@ -772,6 +819,15 @@ class JacLanguageTests(TestCase):
|
|
|
772
819
|
self.assertEqual(len(mypass.errors_had), 0)
|
|
773
820
|
self.assertEqual(len(mypass.warnings_had), 0)
|
|
774
821
|
|
|
822
|
+
def test_circle_override1_type_check_pass(self) -> None:
|
|
823
|
+
"""Test conn assign on edges."""
|
|
824
|
+
mypass = jac_file_to_pass(
|
|
825
|
+
self.examples_abs_path("manual_code/circle.jac"),
|
|
826
|
+
schedule=py_code_gen_typed,
|
|
827
|
+
)
|
|
828
|
+
self.assertEqual(len(mypass.errors_had), 0)
|
|
829
|
+
self.assertEqual(len(mypass.warnings_had), 0)
|
|
830
|
+
|
|
775
831
|
def test_self_with_no_sig(self) -> None: # we can get rid of this, isn't?
|
|
776
832
|
"""Test py ast to Jac ast conversion output."""
|
|
777
833
|
captured_output = io.StringIO()
|
|
@@ -792,7 +848,6 @@ class JacLanguageTests(TestCase):
|
|
|
792
848
|
|
|
793
849
|
def test_multiline_single_tok(self) -> None:
|
|
794
850
|
"""Test conn assign on edges."""
|
|
795
|
-
Jac.get_root()._jac_.edges.clear()
|
|
796
851
|
mypass = jac_file_to_pass(self.fixture_abs_path("byllmissue.jac"))
|
|
797
852
|
self.assertIn("2:5 - 4:8", mypass.ir.pp())
|
|
798
853
|
|
|
@@ -822,7 +877,6 @@ class JacLanguageTests(TestCase):
|
|
|
822
877
|
)
|
|
823
878
|
table = None
|
|
824
879
|
for i in mypass.ir.sym_tab.kid:
|
|
825
|
-
print(i.name)
|
|
826
880
|
if i.name == "GuessTheNumberGame":
|
|
827
881
|
for j in i.kid:
|
|
828
882
|
if j.name == "play":
|
|
@@ -849,3 +903,51 @@ class JacLanguageTests(TestCase):
|
|
|
849
903
|
sys.stdout = sys.__stdout__
|
|
850
904
|
stdout_value = captured_output.getvalue()
|
|
851
905
|
self.assertIn("i work", stdout_value)
|
|
906
|
+
|
|
907
|
+
def test_double_import_exec(self) -> None:
|
|
908
|
+
"""Test importing python."""
|
|
909
|
+
captured_output = io.StringIO()
|
|
910
|
+
sys.stdout = captured_output
|
|
911
|
+
jac_import("dblhello", base_path=self.fixture_abs_path("./"))
|
|
912
|
+
sys.stdout = sys.__stdout__
|
|
913
|
+
stdout_value = captured_output.getvalue()
|
|
914
|
+
self.assertEqual(stdout_value.count("Hello World!"), 1)
|
|
915
|
+
self.assertIn("im still here", stdout_value)
|
|
916
|
+
|
|
917
|
+
def test_cls_method(self) -> None:
|
|
918
|
+
"""Test class method output."""
|
|
919
|
+
captured_output = io.StringIO()
|
|
920
|
+
sys.stdout = captured_output
|
|
921
|
+
jac_import("cls_method", base_path=self.fixture_abs_path("./"))
|
|
922
|
+
sys.stdout = sys.__stdout__
|
|
923
|
+
stdout_value = captured_output.getvalue().split("\n")
|
|
924
|
+
self.assertEqual("MyClass", stdout_value[0])
|
|
925
|
+
self.assertEqual("Hello, World1! Hello, World2!", stdout_value[1])
|
|
926
|
+
self.assertEqual("Hello, World! Hello, World22!", stdout_value[2])
|
|
927
|
+
|
|
928
|
+
def test_list_methods(self) -> None:
|
|
929
|
+
"""Test list_modules, list_walkers, list_nodes, and list_edges."""
|
|
930
|
+
captured_output = io.StringIO()
|
|
931
|
+
sys.stdout = captured_output
|
|
932
|
+
|
|
933
|
+
jac_import("foo", base_path=self.fixture_abs_path("."))
|
|
934
|
+
|
|
935
|
+
sys.stdout = sys.__stdout__
|
|
936
|
+
stdout_value = captured_output.getvalue()
|
|
937
|
+
|
|
938
|
+
self.assertIn(
|
|
939
|
+
"Module: foo",
|
|
940
|
+
stdout_value,
|
|
941
|
+
)
|
|
942
|
+
self.assertIn(
|
|
943
|
+
"Module: bar",
|
|
944
|
+
stdout_value,
|
|
945
|
+
)
|
|
946
|
+
self.assertIn(
|
|
947
|
+
"Walkers in bar:\n - Walker: bar_walk",
|
|
948
|
+
stdout_value,
|
|
949
|
+
)
|
|
950
|
+
self.assertIn("Nodes in bar:\n - Node: Item", stdout_value)
|
|
951
|
+
self.assertIn("Edges in bar:\n - Edge: Link", stdout_value)
|
|
952
|
+
self.assertIn("Item value: 0", stdout_value)
|
|
953
|
+
self.assertIn("Created 5 items.", stdout_value)
|
jaclang/tests/test_reference.py
CHANGED
|
@@ -7,7 +7,7 @@ from typing import Callable, Optional
|
|
|
7
7
|
|
|
8
8
|
import jaclang
|
|
9
9
|
from jaclang.compiler.compile import jac_file_to_pass
|
|
10
|
-
from jaclang.
|
|
10
|
+
from jaclang.runtimelib.context import SUPER_ROOT_ANCHOR
|
|
11
11
|
from jaclang.utils.test import TestCase
|
|
12
12
|
|
|
13
13
|
|
|
@@ -52,7 +52,7 @@ class JacReferenceTests(TestCase):
|
|
|
52
52
|
"""Test file."""
|
|
53
53
|
|
|
54
54
|
def execute_and_capture_output(code: str | bytes, filename: str = "") -> str:
|
|
55
|
-
|
|
55
|
+
SUPER_ROOT_ANCHOR.edges.clear()
|
|
56
56
|
f = io.StringIO()
|
|
57
57
|
with redirect_stdout(f):
|
|
58
58
|
exec(
|
|
@@ -60,7 +60,6 @@ class JacReferenceTests(TestCase):
|
|
|
60
60
|
{
|
|
61
61
|
"__file__": filename,
|
|
62
62
|
"__name__": "__main__",
|
|
63
|
-
"__jac_mod_bundle__": None,
|
|
64
63
|
},
|
|
65
64
|
)
|
|
66
65
|
return f.getvalue()
|
jaclang/utils/helpers.py
CHANGED
|
@@ -5,7 +5,7 @@ import marshal
|
|
|
5
5
|
import os
|
|
6
6
|
import pdb
|
|
7
7
|
import re
|
|
8
|
-
from
|
|
8
|
+
from traceback import TracebackException
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def pascal_to_snake(pascal_string: str) -> str:
|
|
@@ -127,26 +127,6 @@ def auto_generate_refs() -> None:
|
|
|
127
127
|
md_file.write("")
|
|
128
128
|
|
|
129
129
|
|
|
130
|
-
def import_target_to_relative_path(
|
|
131
|
-
level: int, target: str, base_path: Optional[str] = None
|
|
132
|
-
) -> str:
|
|
133
|
-
"""Convert an import target string into a relative file path."""
|
|
134
|
-
if not base_path:
|
|
135
|
-
base_path = os.getcwd()
|
|
136
|
-
parts = target.split(".")
|
|
137
|
-
traversal_levels = level - 1 if level > 0 else 0
|
|
138
|
-
actual_parts = parts[traversal_levels:]
|
|
139
|
-
for _ in range(traversal_levels):
|
|
140
|
-
base_path = os.path.dirname(base_path)
|
|
141
|
-
relative_path = os.path.join(base_path, *actual_parts)
|
|
142
|
-
relative_path = (
|
|
143
|
-
relative_path + ".jac"
|
|
144
|
-
if os.path.exists(relative_path + ".jac")
|
|
145
|
-
else relative_path
|
|
146
|
-
)
|
|
147
|
-
return relative_path
|
|
148
|
-
|
|
149
|
-
|
|
150
130
|
def is_standard_lib_module(module_path: str) -> bool:
|
|
151
131
|
"""Check if a module is a standard library module."""
|
|
152
132
|
import os
|
|
@@ -158,6 +138,50 @@ def is_standard_lib_module(module_path: str) -> bool:
|
|
|
158
138
|
return os.path.isfile(file_path) or os.path.isdir(direc_path)
|
|
159
139
|
|
|
160
140
|
|
|
141
|
+
def dump_traceback(e: Exception) -> str:
|
|
142
|
+
"""Dump the stack frames of the exception."""
|
|
143
|
+
trace_dump = ""
|
|
144
|
+
|
|
145
|
+
# Utility function to get the error line char offset.
|
|
146
|
+
def byte_offset_to_char_offset(string: str, offset: int) -> int:
|
|
147
|
+
return len(string.encode("utf-8")[:offset].decode("utf-8", errors="replace"))
|
|
148
|
+
|
|
149
|
+
tb = TracebackException(type(e), e, e.__traceback__, limit=None, compact=True)
|
|
150
|
+
trace_dump += f"Error: {str(e)}"
|
|
151
|
+
|
|
152
|
+
# The first frame is the call the to the above `exec` function, not usefull to the enduser,
|
|
153
|
+
# and Make the most recent call first.
|
|
154
|
+
tb.stack.pop(0)
|
|
155
|
+
tb.stack.reverse()
|
|
156
|
+
|
|
157
|
+
# FIXME: should be some settings, we should replace to ensure the anchors length match.
|
|
158
|
+
dump_tab_width = 4
|
|
159
|
+
|
|
160
|
+
for idx, frame in enumerate(tb.stack):
|
|
161
|
+
func_signature = frame.name + ("()" if frame.name.isidentifier() else "")
|
|
162
|
+
|
|
163
|
+
# Pretty print the most recent call's location.
|
|
164
|
+
if idx == 0 and (frame.line and frame.line.strip() != ""):
|
|
165
|
+
line_o = frame._original_line.rstrip() # type: ignore [attr-defined]
|
|
166
|
+
line_s = frame.line.rstrip() if frame.line else ""
|
|
167
|
+
stripped_chars = len(line_o) - len(line_s)
|
|
168
|
+
trace_dump += f'\n{" " * (dump_tab_width * 2)}{line_s}'
|
|
169
|
+
if frame.colno is not None and frame.end_colno is not None:
|
|
170
|
+
off_start = byte_offset_to_char_offset(line_o, frame.colno)
|
|
171
|
+
off_end = byte_offset_to_char_offset(line_o, frame.end_colno)
|
|
172
|
+
|
|
173
|
+
# A bunch of caret '^' characters under the error location.
|
|
174
|
+
anchors = (" " * (off_start - stripped_chars - 1)) + "^" * len(
|
|
175
|
+
line_o[off_start:off_end].replace("\t", " " * dump_tab_width)
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
trace_dump += f'\n{" " * (dump_tab_width * 2)}{anchors}'
|
|
179
|
+
|
|
180
|
+
trace_dump += f'\n{" " * dump_tab_width}at {func_signature} {frame.filename}:{frame.lineno}'
|
|
181
|
+
|
|
182
|
+
return trace_dump
|
|
183
|
+
|
|
184
|
+
|
|
161
185
|
class Jdb(pdb.Pdb):
|
|
162
186
|
"""Jac debugger."""
|
|
163
187
|
|
jaclang/utils/test.py
CHANGED
|
@@ -5,15 +5,24 @@ import os
|
|
|
5
5
|
from typing import Callable, Optional
|
|
6
6
|
from unittest import TestCase as _TestCase
|
|
7
7
|
|
|
8
|
+
from _pytest.logging import LogCaptureFixture
|
|
8
9
|
|
|
9
10
|
import jaclang
|
|
10
11
|
from jaclang.compiler.passes import Pass
|
|
11
12
|
from jaclang.utils.helpers import get_ast_nodes_as_snake_case as ast_snakes
|
|
12
13
|
|
|
14
|
+
import pytest
|
|
15
|
+
|
|
13
16
|
|
|
14
17
|
class TestCase(_TestCase):
|
|
15
18
|
"""Base test case for Jaseci."""
|
|
16
19
|
|
|
20
|
+
# Reference: https://stackoverflow.com/a/50375022
|
|
21
|
+
@pytest.fixture(autouse=True)
|
|
22
|
+
def inject_fixtures(self, caplog: LogCaptureFixture) -> None:
|
|
23
|
+
"""Store the logger capture records within the tests."""
|
|
24
|
+
self.caplog = caplog
|
|
25
|
+
|
|
17
26
|
def setUp(self) -> None:
|
|
18
27
|
"""Set up test case."""
|
|
19
28
|
return super().setUp()
|