jaclang 0.7.1__py3-none-any.whl → 0.7.2__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.

Files changed (48) hide show
  1. jaclang/compiler/absyntree.py +51 -14
  2. jaclang/compiler/passes/main/def_impl_match_pass.py +9 -3
  3. jaclang/compiler/passes/main/fuse_typeinfo_pass.py +20 -1
  4. jaclang/compiler/passes/main/import_pass.py +4 -1
  5. jaclang/compiler/passes/main/pyast_gen_pass.py +14 -6
  6. jaclang/compiler/passes/main/pyast_load_pass.py +2 -1
  7. jaclang/compiler/passes/main/pyjac_ast_link_pass.py +6 -1
  8. jaclang/compiler/passes/main/pyout_pass.py +3 -1
  9. jaclang/compiler/passes/main/tests/test_import_pass.py +8 -0
  10. jaclang/compiler/passes/main/tests/test_type_check_pass.py +1 -1
  11. jaclang/compiler/passes/tool/jac_formatter_pass.py +14 -2
  12. jaclang/compiler/passes/tool/tests/fixtures/doc_string.jac +15 -0
  13. jaclang/compiler/passes/tool/tests/test_jac_format_pass.py +7 -5
  14. jaclang/compiler/passes/tool/tests/test_unparse_validate.py +1 -2
  15. jaclang/compiler/symtable.py +21 -1
  16. jaclang/core/aott.py +107 -11
  17. jaclang/core/construct.py +171 -5
  18. jaclang/core/llms/anthropic.py +31 -2
  19. jaclang/core/llms/base.py +3 -3
  20. jaclang/core/llms/groq.py +4 -1
  21. jaclang/core/llms/huggingface.py +4 -1
  22. jaclang/core/llms/ollama.py +4 -1
  23. jaclang/core/llms/openai.py +6 -2
  24. jaclang/core/llms/togetherai.py +4 -1
  25. jaclang/langserve/engine.py +99 -115
  26. jaclang/langserve/server.py +27 -5
  27. jaclang/langserve/tests/fixtures/circle_pure.impl.jac +8 -4
  28. jaclang/langserve/tests/fixtures/circle_pure.jac +2 -2
  29. jaclang/langserve/tests/test_server.py +123 -0
  30. jaclang/langserve/utils.py +100 -10
  31. jaclang/plugin/default.py +25 -83
  32. jaclang/plugin/feature.py +10 -12
  33. jaclang/plugin/tests/test_features.py +0 -33
  34. jaclang/settings.py +1 -0
  35. jaclang/tests/fixtures/byllmissue.jac +3 -0
  36. jaclang/tests/fixtures/hash_init_check.jac +17 -0
  37. jaclang/tests/fixtures/math_question.jpg +0 -0
  38. jaclang/tests/fixtures/nosigself.jac +19 -0
  39. jaclang/tests/fixtures/walker_override.jac +21 -0
  40. jaclang/tests/fixtures/with_llm_vision.jac +25 -0
  41. jaclang/tests/test_language.py +61 -11
  42. jaclang/utils/treeprinter.py +19 -2
  43. {jaclang-0.7.1.dist-info → jaclang-0.7.2.dist-info}/METADATA +3 -2
  44. {jaclang-0.7.1.dist-info → jaclang-0.7.2.dist-info}/RECORD +46 -41
  45. jaclang/core/memory.py +0 -48
  46. jaclang/core/shelve_storage.py +0 -55
  47. {jaclang-0.7.1.dist-info → jaclang-0.7.2.dist-info}/WHEEL +0 -0
  48. {jaclang-0.7.1.dist-info → jaclang-0.7.2.dist-info}/entry_points.txt +0 -0
@@ -1,12 +1,15 @@
1
1
  """Utility functions for the language server."""
2
2
 
3
3
  import asyncio
4
+ import builtins
4
5
  from functools import wraps
5
6
  from typing import Any, Awaitable, Callable, Coroutine, Optional, ParamSpec, TypeVar
6
7
 
7
8
  import jaclang.compiler.absyntree as ast
8
- from jaclang.compiler.symtable import SymbolTable
9
+ from jaclang.compiler.codeloc import CodeLocInfo
10
+ from jaclang.compiler.symtable import Symbol, SymbolTable
9
11
 
12
+ import lsprotocol.types as lspt
10
13
 
11
14
  T = TypeVar("T", bound=Callable[..., Coroutine[Any, Any, Any]])
12
15
  P = ParamSpec("P")
@@ -55,17 +58,23 @@ def sym_tab_list(sym_tab: SymbolTable, file_path: str) -> list[SymbolTable]:
55
58
  return sym_tabs
56
59
 
57
60
 
58
- def find_deepest_node_at_pos(
61
+ def find_deepest_symbol_node_at_pos(
59
62
  node: ast.AstNode, line: int, character: int
60
- ) -> Optional[ast.AstNode]:
61
- """Return the deepest node that contains the given position."""
63
+ ) -> Optional[ast.AstSymbolNode]:
64
+ """Return the deepest symbol node that contains the given position."""
65
+ last_symbol_node = None
66
+
62
67
  if position_within_node(node, line, character):
63
- for i in node.kid:
64
- if position_within_node(i, line, character):
65
- return find_deepest_node_at_pos(i, line, character)
66
- return node
67
- else:
68
- return None
68
+ if isinstance(node, ast.AstSymbolNode):
69
+ last_symbol_node = node
70
+
71
+ for child in node.kid:
72
+ if position_within_node(child, line, character):
73
+ deeper_node = find_deepest_symbol_node_at_pos(child, line, character)
74
+ if deeper_node is not None:
75
+ last_symbol_node = deeper_node
76
+
77
+ return last_symbol_node
69
78
 
70
79
 
71
80
  def position_within_node(node: ast.AstNode, line: int, character: int) -> bool:
@@ -88,3 +97,84 @@ def position_within_node(node: ast.AstNode, line: int, character: int) -> bool:
88
97
  ):
89
98
  return True
90
99
  return False
100
+
101
+
102
+ def collect_symbols(node: SymbolTable) -> list[lspt.DocumentSymbol]:
103
+ """Recursively collect symbols from the AST."""
104
+ symbols = []
105
+ if node is None:
106
+ return symbols
107
+
108
+ for key, item in node.tab.items():
109
+ if key in dir(builtins):
110
+ continue
111
+ if item in [owner_sym(tab) for tab in node.kid]:
112
+ continue
113
+ else:
114
+
115
+ pos = create_range(item.defn[0].loc)
116
+ symbol = lspt.DocumentSymbol(
117
+ name=key,
118
+ kind=kind_map(item.defn[0]),
119
+ range=pos,
120
+ selection_range=pos,
121
+ children=[],
122
+ )
123
+ symbols.append(symbol)
124
+
125
+ for sub_tab in node.kid:
126
+ sub_symbols = collect_symbols(sub_tab)
127
+
128
+ if isinstance(
129
+ sub_tab.owner,
130
+ (ast.IfStmt, ast.ElseStmt, ast.WhileStmt, ast.IterForStmt, ast.InForStmt),
131
+ ):
132
+ symbols.extend(sub_symbols)
133
+ else:
134
+ sub_pos = create_range(sub_tab.owner.loc)
135
+ symbol = lspt.DocumentSymbol(
136
+ name=sub_tab.name,
137
+ kind=kind_map(sub_tab.owner),
138
+ range=sub_pos,
139
+ selection_range=sub_pos,
140
+ children=sub_symbols,
141
+ )
142
+ symbols.append(symbol)
143
+
144
+ return symbols
145
+
146
+
147
+ def owner_sym(table: SymbolTable) -> Optional[Symbol]:
148
+ """Get owner sym."""
149
+ if table.has_parent() and isinstance(table.owner, ast.AstSymbolNode):
150
+ return table.parent.lookup(table.owner.sym_name)
151
+ return None
152
+
153
+
154
+ def create_range(loc: CodeLocInfo) -> lspt.Range:
155
+ """Create an lspt.Range from a location object."""
156
+ return lspt.Range(
157
+ start=lspt.Position(line=loc.first_line - 1, character=loc.col_start - 1),
158
+ end=lspt.Position(line=loc.last_line - 1, character=loc.col_end - 1),
159
+ )
160
+
161
+
162
+ def kind_map(sub_tab: ast.AstNode) -> lspt.SymbolKind:
163
+ """Map the symbol node to an lspt.SymbolKind."""
164
+ return (
165
+ lspt.SymbolKind.Function
166
+ if isinstance(sub_tab, (ast.Ability, ast.AbilityDef))
167
+ else (
168
+ lspt.SymbolKind.Class
169
+ if isinstance(sub_tab, (ast.Architype, ast.ArchDef))
170
+ else (
171
+ lspt.SymbolKind.Module
172
+ if isinstance(sub_tab, ast.Module)
173
+ else (
174
+ lspt.SymbolKind.Enum
175
+ if isinstance(sub_tab, (ast.Enum, ast.EnumDef))
176
+ else lspt.SymbolKind.Variable
177
+ )
178
+ )
179
+ )
180
+ )
jaclang/plugin/default.py CHANGED
@@ -7,11 +7,10 @@ import html
7
7
  import os
8
8
  import pickle
9
9
  import types
10
- from contextvars import ContextVar
10
+ from collections import OrderedDict
11
11
  from dataclasses import field
12
12
  from functools import wraps
13
13
  from typing import Any, Callable, Optional, Type, Union
14
- from uuid import UUID
15
14
 
16
15
  from jaclang.compiler.absyntree import Module
17
16
  from jaclang.compiler.constant import EdgeDir, colors
@@ -20,27 +19,27 @@ from jaclang.core.aott import (
20
19
  extract_non_primary_type,
21
20
  get_all_type_explanations,
22
21
  get_info_types,
23
- get_object_string,
24
- get_type_annotation,
22
+ get_input_information,
25
23
  )
26
24
  from jaclang.core.construct import (
27
25
  Architype,
28
26
  DSFunc,
29
27
  EdgeAnchor,
30
28
  EdgeArchitype,
29
+ ExecutionContext,
31
30
  GenericEdge,
32
31
  JacTestCheck,
32
+ Memory,
33
33
  NodeAnchor,
34
34
  NodeArchitype,
35
35
  ObjectAnchor,
36
36
  Root,
37
37
  WalkerAnchor,
38
38
  WalkerArchitype,
39
+ exec_context,
39
40
  )
40
41
  from jaclang.core.importer import jac_importer
41
- from jaclang.core.memory import Memory
42
42
  from jaclang.core.registry import SemInfo, SemRegistry, SemScope
43
- from jaclang.core.shelve_storage import ShelveStorage
44
43
  from jaclang.core.utils import traverse_graph
45
44
  from jaclang.plugin.feature import JacFeature as Jac
46
45
  from jaclang.plugin.spec import T
@@ -70,65 +69,6 @@ __all__ = [
70
69
  hookimpl = pluggy.HookimplMarker("jac")
71
70
 
72
71
 
73
- class ExecutionContext:
74
- """Default Execution Context implementation."""
75
-
76
- mem: Optional[Memory]
77
- root: Optional[Root]
78
-
79
- def __init__(self) -> None:
80
- super().__init__()
81
- self.mem = ShelveStorage()
82
- self.root = None
83
-
84
- def init_memory(self, session: str = "") -> None:
85
- if session:
86
- self.mem = ShelveStorage(session)
87
- else:
88
- self.mem = Memory()
89
-
90
- def get_root(self) -> Root:
91
- if self.mem is None:
92
- raise ValueError("Memory not initialized")
93
-
94
- if not self.root:
95
- root = self.mem.get_obj(UUID(int=0))
96
- if root is None:
97
- self.root = Root()
98
- self.mem.save_obj(self.root, persistent=self.root._jac_.persistent)
99
- elif not isinstance(root, Root):
100
- raise ValueError(f"Invalid root object: {root}")
101
- else:
102
- self.root = root
103
- return self.root
104
-
105
- def get_obj(self, obj_id: UUID) -> Architype | None:
106
- """Get object from memory."""
107
- if self.mem is None:
108
- raise ValueError("Memory not initialized")
109
-
110
- return self.mem.get_obj(obj_id)
111
-
112
- def save_obj(self, item: Architype, persistent: bool) -> None:
113
- """Save object to memory."""
114
- if self.mem is None:
115
- raise ValueError("Memory not initialized")
116
-
117
- self.mem.save_obj(item, persistent)
118
-
119
- def reset(self) -> None:
120
- """Reset the execution context."""
121
- if self.mem:
122
- self.mem.close()
123
- self.mem = None
124
- self.root = None
125
-
126
-
127
- ExecContext: ContextVar[ExecutionContext | None] = ContextVar(
128
- "ExecutionContext", default=None
129
- )
130
-
131
-
132
72
  class JacFeatureDefaults:
133
73
  """Jac Feature."""
134
74
 
@@ -138,20 +78,20 @@ class JacFeatureDefaults:
138
78
  @hookimpl
139
79
  def context(session: str = "") -> ExecutionContext:
140
80
  """Get the execution context."""
141
- ctx = ExecContext.get()
81
+ ctx = exec_context.get()
142
82
  if ctx is None:
143
83
  ctx = ExecutionContext()
144
- ExecContext.set(ctx)
84
+ exec_context.set(ctx)
145
85
  return ctx
146
86
 
147
87
  @staticmethod
148
88
  @hookimpl
149
89
  def reset_context() -> None:
150
90
  """Reset the execution context."""
151
- ctx = ExecContext.get()
91
+ ctx = exec_context.get()
152
92
  if ctx:
153
93
  ctx.reset()
154
- ExecContext.set(None)
94
+ exec_context.set(None)
155
95
 
156
96
  @staticmethod
157
97
  @hookimpl
@@ -179,12 +119,20 @@ class JacFeatureDefaults:
179
119
  cls._jac_entry_funcs_ = on_entry # type: ignore
180
120
  cls._jac_exit_funcs_ = on_exit # type: ignore
181
121
  else:
182
- cls._jac_entry_funcs_ = cls._jac_entry_funcs_ + [
183
- x for x in on_entry if x not in cls._jac_entry_funcs_
184
- ]
185
- cls._jac_exit_funcs_ = cls._jac_exit_funcs_ + [
186
- x for x in on_exit if x not in cls._jac_exit_funcs_
187
- ]
122
+ new_entry_funcs = OrderedDict(zip([i.name for i in on_entry], on_entry))
123
+ entry_funcs = OrderedDict(
124
+ zip([i.name for i in cls._jac_entry_funcs_], cls._jac_entry_funcs_)
125
+ )
126
+ entry_funcs.update(new_entry_funcs)
127
+ cls._jac_entry_funcs_ = list(entry_funcs.values())
128
+
129
+ new_exit_funcs = OrderedDict(zip([i.name for i in on_exit], on_exit))
130
+ exit_funcs = OrderedDict(
131
+ zip([i.name for i in cls._jac_exit_funcs_], cls._jac_exit_funcs_)
132
+ )
133
+ exit_funcs.update(new_exit_funcs)
134
+ cls._jac_exit_funcs_ = list(exit_funcs.values())
135
+
188
136
  inner_init = cls.__init__ # type: ignore
189
137
 
190
138
  @wraps(inner_init)
@@ -698,14 +646,8 @@ class JacFeatureDefaults:
698
646
  incl_info = [x for x in incl_info if not isinstance(x[1], type)]
699
647
  information, collected_types = get_info_types(_scope, mod_registry, incl_info)
700
648
  type_collector.extend(collected_types)
701
- inputs_information_list = []
702
- for i in inputs:
703
- typ_anno = get_type_annotation(i[3])
704
- type_collector.extend(extract_non_primary_type(typ_anno))
705
- inputs_information_list.append(
706
- f"{i[0]} ({i[2]}) ({typ_anno}) = {get_object_string(i[3])}"
707
- )
708
- inputs_information = "\n".join(inputs_information_list)
649
+
650
+ inputs_information = get_input_information(inputs, type_collector)
709
651
 
710
652
  output_information = f"{outputs[0]} ({outputs[1]})"
711
653
  type_collector.extend(extract_non_primary_type(outputs[1]))
jaclang/plugin/feature.py CHANGED
@@ -3,22 +3,20 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import types
6
- from typing import Any, Callable, Optional, TYPE_CHECKING, Type, Union
6
+ from typing import Any, Callable, Optional, Type, Union
7
7
 
8
8
  from jaclang.compiler.absyntree import Module
9
+ from jaclang.core.construct import (
10
+ Architype,
11
+ EdgeArchitype,
12
+ Memory,
13
+ NodeArchitype,
14
+ Root,
15
+ WalkerArchitype,
16
+ )
17
+ from jaclang.plugin.default import ExecutionContext
9
18
  from jaclang.plugin.spec import JacBuiltin, JacCmdSpec, JacFeatureSpec, T
10
19
 
11
- if TYPE_CHECKING:
12
- from jaclang.core.construct import (
13
- Architype,
14
- EdgeArchitype,
15
- NodeArchitype,
16
- WalkerArchitype,
17
- Root,
18
- )
19
- from jaclang.plugin.default import ExecutionContext
20
- from jaclang.core.memory import Memory
21
-
22
20
 
23
21
  import pluggy
24
22
 
@@ -1,12 +1,8 @@
1
1
  """Tests for Jac parser."""
2
2
 
3
3
  import inspect
4
- import io
5
- import sys
6
- import traceback
7
4
  from typing import List, Type
8
5
 
9
- from jaclang.cli import cli
10
6
  from jaclang.plugin.default import JacFeatureDefaults
11
7
  from jaclang.plugin.feature import JacFeature
12
8
  from jaclang.plugin.spec import JacFeatureSpec
@@ -58,32 +54,3 @@ class TestFeatures(TestCase):
58
54
  self.assertEqual(jac_feature_spec_methods, jac_feature_defaults_methods)
59
55
  for i in jac_feature_spec_methods:
60
56
  self.assertIn(i, jac_feature_methods)
61
-
62
- def test_impl_match_error_reporting(self) -> None:
63
- """Basic test for error reporting."""
64
- captured_output = io.StringIO()
65
- original_stderr = sys.stderr
66
- sys.stderr = captured_output
67
-
68
- try:
69
- # Execute the function that is expected to raise an exception
70
- cli.run(self.fixture_abs_path("impl_match.jac")) # type: ignore
71
- except Exception:
72
- # Print the full stack trace to the captured output
73
- traceback.print_exc(file=captured_output)
74
- finally:
75
- # Restore the original stderr
76
- sys.stderr = original_stderr
77
-
78
- # Retrieve the captured output
79
- stderr_val = captured_output.getvalue()
80
- # Assertions or verifications
81
- try:
82
- self.assertIn("impl_match.jac", stderr_val)
83
- self.assertIn("impl_match_impl.jac", stderr_val)
84
- self.assertLess(
85
- stderr_val.index("impl_match.jac"),
86
- stderr_val.index("impl_match_impl.jac"),
87
- )
88
- except AssertionError:
89
- self.skipTest("Error reporting not implemented yet")
jaclang/settings.py CHANGED
@@ -12,6 +12,7 @@ class Settings:
12
12
  # Debug configuration
13
13
  fuse_type_info_debug: bool = False
14
14
  filter_sym_builtins: bool = True
15
+ ast_symbol_info_detailed: bool = False
15
16
 
16
17
  # Import configuration
17
18
  py_raise: bool = False
@@ -0,0 +1,3 @@
1
+ with entry {
2
+ my_thing = YourThing(level=thingy by llm());
3
+ }
@@ -0,0 +1,17 @@
1
+ obj TYPE {
2
+ can init() {
3
+ DICT:dict = {};
4
+ DICT[self] = 1;
5
+ }
6
+ }
7
+
8
+ obj TASK:TYPE: {
9
+ can init() {
10
+ TYPE.init(self);
11
+ }
12
+ }
13
+
14
+ with entry {
15
+ TASK();
16
+ print('Test Passed');
17
+ }
Binary file
@@ -0,0 +1,19 @@
1
+ obj Foo {
2
+ has a: int = 5;
3
+
4
+ can say {
5
+ print(self.a);
6
+ }
7
+
8
+ can say2;
9
+ }
10
+
11
+ :o:Foo:c:say2 {
12
+ print(self.a);
13
+ }
14
+
15
+ with entry {
16
+ f = Foo();
17
+ f.say();
18
+ f.say2();
19
+ }
@@ -0,0 +1,21 @@
1
+ walker a {
2
+ can foo with `root entry {
3
+ print("foo");
4
+ }
5
+ }
6
+
7
+ walker b :a: {
8
+ can bar with `root entry {
9
+ print("bar");
10
+ }
11
+ }
12
+
13
+ walker c :b: {
14
+ override can foo with `root entry {
15
+ print("baz");
16
+ }
17
+ }
18
+
19
+ with entry {
20
+ root spawn c();
21
+ }
@@ -0,0 +1,25 @@
1
+ import:py from jaclang.core.llms, BaseLLM;
2
+ import:py from PIL, Image;
3
+ import:py os;
4
+
5
+ obj model:BaseLLM: {
6
+ can init {
7
+ self.verbose = False;
8
+ self.max_tries = 1;
9
+ }
10
+ can __infer__(meaning_in: str, **kwargs: dict) {
11
+ print(kwargs);
12
+ print(meaning_in);
13
+ return "[Output] Something";
14
+ }
15
+ }
16
+ glob llm = model();
17
+
18
+ can 'Solve the Given Math Question'
19
+ solve_math_question(question_img: 'Image of the Question': Image) -> 'Answer to the Question': str
20
+ by llm(method="Chain-of-Thoughts");
21
+
22
+ with entry {
23
+ question_img = Image.open(os.path.join(os.path.dirname(__file__), 'math_question.jpg'));
24
+ print(solve_math_question(question_img));
25
+ }
@@ -6,6 +6,7 @@ import pickle
6
6
  import sys
7
7
  import sysconfig
8
8
 
9
+
9
10
  from jaclang import jac_import
10
11
  from jaclang.cli import cli
11
12
  from jaclang.compiler.compile import jac_file_to_pass, jac_pass_to_pass, jac_str_to_pass
@@ -119,16 +120,10 @@ class JacLanguageTests(TestCase):
119
120
  self.assertIn("{'temperature': 0.7}", stdout_value)
120
121
  self.assertIn("Emoji Representation (str)", stdout_value)
121
122
  self.assertIn('Text Input (input) (str) = "Lets move to paris"', stdout_value)
122
- try:
123
- self.assertIn(
124
- "Examples of Text to Emoji (emoji_examples) (list[dict[str,str]])"
125
- ' = [{"input": "I love tp drink pina coladas"',
126
- stdout_value,
127
- )
128
- except AssertionError:
129
- self.skipTest(
130
- "This error only happens in certain enviornments, check later."
131
- )
123
+ self.assertIn(
124
+ ' = [{"input": "I love tp drink pina coladas"',
125
+ stdout_value,
126
+ )
132
127
 
133
128
  def test_with_llm_method(self) -> None:
134
129
  """Parse micro jac file."""
@@ -187,7 +182,7 @@ class JacLanguageTests(TestCase):
187
182
  self.assertIn("14/03/1879", stdout_value)
188
183
  self.assertNotIn(
189
184
  'University (University) (obj) = type(__module__="with_llm_type", __doc__=None, '
190
- "_jac_entry_funcs_=[], _jac_exit_funcs_=[], __init__=function(__wrapped__=function()))",
185
+ "_jac_entry_funcs_`=[`], _jac_exit_funcs_=[], __init__=function(__wrapped__=function()))",
191
186
  stdout_value,
192
187
  )
193
188
  desired_output_count = stdout_value.count(
@@ -195,6 +190,25 @@ class JacLanguageTests(TestCase):
195
190
  )
196
191
  self.assertEqual(desired_output_count, 2)
197
192
 
193
+ def test_with_llm_vision(self) -> None:
194
+ """Test MTLLLM Vision Implementation."""
195
+ try:
196
+ captured_output = io.StringIO()
197
+ sys.stdout = captured_output
198
+ jac_import("with_llm_vision", base_path=self.fixture_abs_path("./"))
199
+ sys.stdout = sys.__stdout__
200
+ stdout_value = captured_output.getvalue()
201
+ self.assertIn(
202
+ "{'type': 'text', 'text': '\\n[System Prompt]\\n", stdout_value[:500]
203
+ )
204
+ self.assertNotIn(
205
+ " {'type': 'text', 'text': 'Image of the Question (question_img) (Image) = '}, "
206
+ "{'type': 'image_url', 'image_url': {'url': 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQAB",
207
+ stdout_value[:500],
208
+ )
209
+ except Exception:
210
+ self.skipTest("This test requires Pillow to be installed.")
211
+
198
212
  def test_ignore(self) -> None:
199
213
  """Parse micro jac file."""
200
214
  Jac.get_root()._jac_.edges.clear()
@@ -829,3 +843,39 @@ class JacLanguageTests(TestCase):
829
843
  stdout_value = captured_output.getvalue()
830
844
  self.assertIn("Deep convo is imported", stdout_value)
831
845
  settings.py_raise = settings.py_raise_deep = False
846
+
847
+ def test_override_walker_inherit(self) -> None:
848
+ """Test py ast to Jac ast conversion output."""
849
+ captured_output = io.StringIO()
850
+ sys.stdout = captured_output
851
+ jac_import("walker_override", base_path=self.fixture_abs_path("./"))
852
+ sys.stdout = sys.__stdout__
853
+ stdout_value = captured_output.getvalue()
854
+ self.assertEqual("baz\nbar\n", stdout_value)
855
+
856
+ def test_ds_type_check_pass(self) -> None:
857
+ """Test conn assign on edges."""
858
+ Jac.get_root()._jac_.edges.clear()
859
+ mypass = jac_file_to_pass(
860
+ self.fixture_abs_path("../../../examples/micro/simple_walk.jac")
861
+ )
862
+ self.assertEqual(len(mypass.errors_had), 0)
863
+ self.assertEqual(len(mypass.warnings_had), 0)
864
+
865
+ def test_self_with_no_sig(self) -> None: # we can get rid of this, isn't?
866
+ """Test py ast to Jac ast conversion output."""
867
+ captured_output = io.StringIO()
868
+ sys.stdout = captured_output
869
+ jac_import("nosigself", base_path=self.fixture_abs_path("./"))
870
+ sys.stdout = sys.__stdout__
871
+ stdout_value = captured_output.getvalue()
872
+ self.assertEqual(stdout_value.count("5"), 2)
873
+
874
+ def test_hash_init_check(self) -> None: # we can get rid of this, isn't?
875
+ """Test py ast to Jac ast conversion output."""
876
+ captured_output = io.StringIO()
877
+ sys.stdout = captured_output
878
+ jac_import("hash_init_check", base_path=self.fixture_abs_path("./"))
879
+ sys.stdout = sys.__stdout__
880
+ stdout_value = captured_output.getvalue()
881
+ self.assertIn("Test Passed", stdout_value)
@@ -100,12 +100,29 @@ def print_ast_tree(
100
100
  if isinstance(node, AstSymbolNode) and node.sym_info.typ_sym_table
101
101
  else "SymbolTable: None" if isinstance(node, AstSymbolNode) else ""
102
102
  )
103
+
103
104
  if isinstance(node, Token) and isinstance(node, AstSymbolNode):
104
- return f"{node.__class__.__name__} - {node.value} - Type: {node.sym_info.typ}, {access} {sym_table_link}"
105
+ out = f"{node.__class__.__name__} - {node.value} - Type: {node.sym_info.typ}, {access} {sym_table_link}"
106
+ if settings.ast_symbol_info_detailed:
107
+ symbol = (
108
+ node.sym_link.sym_path_str
109
+ if node.sym_link
110
+ else "<No Symbol is associated with this node>"
111
+ )
112
+ out += f" SymbolPath: {symbol}"
113
+ return out
105
114
  elif isinstance(node, Token):
106
115
  return f"{node.__class__.__name__} - {node.value}, {access}"
107
116
  elif isinstance(node, AstSymbolNode):
108
- return f"{node.__class__.__name__} - {node.sym_name} - Type: {node.sym_info.typ}, {access} {sym_table_link}"
117
+ out = f"{node.__class__.__name__} - {node.sym_name} - Type: {node.sym_info.typ}, {access} {sym_table_link}"
118
+ if settings.ast_symbol_info_detailed:
119
+ symbol = (
120
+ node.sym_link.sym_path_str
121
+ if node.sym_link
122
+ else "<No Symbol is associated with this node>"
123
+ )
124
+ out += f" SymbolPath: {symbol}"
125
+ return out
109
126
  else:
110
127
  return f"{node.__class__.__name__}, {access}"
111
128
 
@@ -1,15 +1,16 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jaclang
3
- Version: 0.7.1
3
+ Version: 0.7.2
4
4
  Summary: Jac is a unique and powerful programming language that runs on top of Python, offering an unprecedented level of intelligence and intuitive understanding.
5
5
  Home-page: https://jaseci.org
6
6
  License: MIT
7
7
  Keywords: jac,jaclang,programming-language,machine-learning,artificial-intelligence
8
8
  Author: Jason Mars
9
9
  Author-email: jason@jaseci.org
10
- Requires-Python: >=3.12.0,<4.0.0
10
+ Requires-Python: >=3.11.0,<4.0.0
11
11
  Classifier: License :: OSI Approved :: MIT License
12
12
  Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.11
13
14
  Classifier: Programming Language :: Python :: 3.12
14
15
  Provides-Extra: llm
15
16
  Project-URL: Documentation, https://jac-lang.org