jaclang 0.7.11__py3-none-any.whl → 0.7.13__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 +10 -2
- jaclang/compiler/absyntree.py +10 -2
- jaclang/compiler/parser.py +2 -1
- jaclang/compiler/passes/main/pyast_gen_pass.py +238 -32
- jaclang/compiler/passes/main/pyast_load_pass.py +3 -1
- jaclang/compiler/passes/main/type_check_pass.py +0 -17
- jaclang/compiler/tests/test_importer.py +1 -1
- jaclang/core/importer.py +126 -89
- jaclang/langserve/engine.py +177 -165
- jaclang/langserve/server.py +19 -7
- jaclang/langserve/tests/fixtures/base_module_structure.jac +28 -2
- jaclang/langserve/tests/fixtures/import_include_statements.jac +1 -1
- jaclang/langserve/tests/test_server.py +53 -64
- jaclang/langserve/utils.py +266 -0
- jaclang/plugin/default.py +2 -2
- jaclang/plugin/feature.py +2 -2
- jaclang/plugin/spec.py +2 -2
- jaclang/tests/fixtures/deep/one_lev.jac +3 -0
- jaclang/tests/fixtures/needs_import.jac +1 -1
- jaclang/tests/test_cli.py +6 -6
- {jaclang-0.7.11.dist-info → jaclang-0.7.13.dist-info}/METADATA +1 -1
- {jaclang-0.7.11.dist-info → jaclang-0.7.13.dist-info}/RECORD +24 -24
- {jaclang-0.7.11.dist-info → jaclang-0.7.13.dist-info}/WHEEL +0 -0
- {jaclang-0.7.11.dist-info → jaclang-0.7.13.dist-info}/entry_points.txt +0 -0
jaclang/core/importer.py
CHANGED
|
@@ -15,51 +15,67 @@ from jaclang.core.utils import sys_path_context
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
def handle_directory(
|
|
18
|
-
module_name: str, full_mod_path: str, mod_bundle: Module
|
|
18
|
+
module_name: str, full_mod_path: str, mod_bundle: Optional[Module]
|
|
19
19
|
) -> types.ModuleType:
|
|
20
20
|
"""Import from a directory that potentially contains multiple Jac modules."""
|
|
21
21
|
module = types.ModuleType(module_name)
|
|
22
22
|
module.__name__ = module_name
|
|
23
23
|
module.__path__ = [full_mod_path]
|
|
24
|
+
module.__file__ = None
|
|
24
25
|
module.__dict__["__jac_mod_bundle__"] = mod_bundle
|
|
25
|
-
if
|
|
26
|
+
if module_name not in sys.modules:
|
|
26
27
|
sys.modules[module_name] = module
|
|
27
28
|
return module
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
def process_items(
|
|
31
32
|
module: types.ModuleType,
|
|
32
|
-
items: dict[str, Union[str,
|
|
33
|
+
items: dict[str, Union[str, Optional[str]]],
|
|
33
34
|
caller_dir: str,
|
|
35
|
+
lang: Optional[str],
|
|
34
36
|
mod_bundle: Optional[Module] = None,
|
|
35
37
|
cachable: bool = True,
|
|
36
|
-
) ->
|
|
38
|
+
) -> list:
|
|
37
39
|
"""Process items within a module by handling renaming and potentially loading missing attributes."""
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
unique_loaded_items = []
|
|
41
|
+
|
|
42
|
+
def handle_item_loading(item: str, alias: Union[str, Optional[str]]) -> None:
|
|
43
|
+
if item:
|
|
44
|
+
unique_loaded_items.append(item)
|
|
45
|
+
setattr(module, name, item)
|
|
46
|
+
if alias and alias != name and not isinstance(alias, bool):
|
|
47
|
+
setattr(module, alias, item)
|
|
48
|
+
|
|
43
49
|
for name, alias in items.items():
|
|
44
50
|
try:
|
|
45
51
|
item = getattr(module, name)
|
|
46
|
-
|
|
47
|
-
setattr(module, alias, item)
|
|
52
|
+
handle_item_loading(item, alias)
|
|
48
53
|
except AttributeError:
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
module
|
|
53
|
-
|
|
54
|
-
jac_file_path=jac_file_path,
|
|
55
|
-
mod_bundle=mod_bundle,
|
|
56
|
-
cachable=cachable,
|
|
57
|
-
caller_dir=caller_dir,
|
|
54
|
+
if lang == "jac":
|
|
55
|
+
jac_file_path = (
|
|
56
|
+
os.path.join(module.__path__[0], f"{name}.jac")
|
|
57
|
+
if hasattr(module, "__path__")
|
|
58
|
+
else module.__file__
|
|
58
59
|
)
|
|
59
|
-
if
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
if jac_file_path and os.path.isfile(jac_file_path):
|
|
61
|
+
item = load_jac_file(
|
|
62
|
+
module=module,
|
|
63
|
+
name=name,
|
|
64
|
+
jac_file_path=jac_file_path,
|
|
65
|
+
mod_bundle=mod_bundle,
|
|
66
|
+
cachable=cachable,
|
|
67
|
+
caller_dir=caller_dir,
|
|
68
|
+
)
|
|
69
|
+
handle_item_loading(item, alias)
|
|
70
|
+
elif jac_file_path and os.path.isdir(jac_file_path[:-4]):
|
|
71
|
+
item = handle_directory(name, jac_file_path[:-4], mod_bundle)
|
|
72
|
+
handle_item_loading(item, alias)
|
|
73
|
+
else:
|
|
74
|
+
if hasattr(module, "__path__"):
|
|
75
|
+
full_module_name = f"{module.__name__}.{name}"
|
|
76
|
+
item = importlib.import_module(full_module_name)
|
|
77
|
+
handle_item_loading(item, alias)
|
|
78
|
+
return unique_loaded_items
|
|
63
79
|
|
|
64
80
|
|
|
65
81
|
def load_jac_file(
|
|
@@ -138,24 +154,23 @@ def jac_importer(
|
|
|
138
154
|
override_name: Optional[str] = None,
|
|
139
155
|
mod_bundle: Optional[Module | str] = None,
|
|
140
156
|
lng: Optional[str] = "jac",
|
|
141
|
-
items: Optional[dict[str, Union[str,
|
|
142
|
-
) ->
|
|
157
|
+
items: Optional[dict[str, Union[str, Optional[str]]]] = None,
|
|
158
|
+
) -> tuple[types.ModuleType, ...]:
|
|
143
159
|
"""Core Import Process."""
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
)
|
|
160
|
+
unique_loaded_items = []
|
|
161
|
+
dir_path, file_name = path.split(path.join(*(target.split("."))))
|
|
147
162
|
module_name = path.splitext(file_name)[0]
|
|
148
163
|
package_path = dir_path.replace(path.sep, ".")
|
|
149
|
-
|
|
150
164
|
if (
|
|
151
165
|
not override_name
|
|
152
166
|
and package_path
|
|
153
167
|
and f"{package_path}.{module_name}" in sys.modules
|
|
154
168
|
):
|
|
155
|
-
|
|
169
|
+
module = sys.modules[f"{package_path}.{module_name}"]
|
|
156
170
|
elif not override_name and not package_path and module_name in sys.modules:
|
|
157
|
-
|
|
158
|
-
|
|
171
|
+
module = sys.modules[module_name]
|
|
172
|
+
else:
|
|
173
|
+
module = None
|
|
159
174
|
valid_mod_bundle = (
|
|
160
175
|
sys.modules[mod_bundle].__jac_mod_bundle__
|
|
161
176
|
if isinstance(mod_bundle, str)
|
|
@@ -166,54 +181,61 @@ def jac_importer(
|
|
|
166
181
|
|
|
167
182
|
caller_dir = get_caller_dir(target, base_path, dir_path)
|
|
168
183
|
full_target = path.normpath(path.join(caller_dir, file_name))
|
|
184
|
+
if not module:
|
|
185
|
+
if os.path.isdir(full_target):
|
|
186
|
+
module = handle_directory(module_name, full_target, valid_mod_bundle)
|
|
187
|
+
else:
|
|
188
|
+
full_target += ".jac" if lng == "jac" else ".py"
|
|
189
|
+
module_name = path.splitext(file_name)[0]
|
|
190
|
+
package_path = dir_path.replace(path.sep, ".")
|
|
169
191
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
192
|
+
if lng == "py":
|
|
193
|
+
module, *unique_loaded_items = py_import(
|
|
194
|
+
target=target,
|
|
195
|
+
items=items,
|
|
196
|
+
absorb=absorb,
|
|
197
|
+
mdl_alias=mdl_alias,
|
|
198
|
+
caller_dir=caller_dir,
|
|
199
|
+
)
|
|
200
|
+
else:
|
|
201
|
+
module_name = override_name if override_name else module_name
|
|
202
|
+
module = create_jac_py_module(
|
|
203
|
+
valid_mod_bundle,
|
|
204
|
+
module_name,
|
|
205
|
+
package_path,
|
|
206
|
+
full_target,
|
|
207
|
+
)
|
|
208
|
+
codeobj = get_codeobj(
|
|
209
|
+
full_target,
|
|
210
|
+
module_name,
|
|
211
|
+
valid_mod_bundle,
|
|
212
|
+
cachable,
|
|
213
|
+
caller_dir=caller_dir,
|
|
214
|
+
)
|
|
215
|
+
try:
|
|
216
|
+
if not codeobj:
|
|
217
|
+
raise ImportError(f"No bytecode found for {full_target}")
|
|
218
|
+
with sys_path_context(caller_dir):
|
|
219
|
+
exec(codeobj, module.__dict__)
|
|
220
|
+
except Exception as e:
|
|
221
|
+
raise ImportError(f"Error importing {full_target}: {str(e)}")
|
|
222
|
+
unique_loaded_items = (
|
|
223
|
+
process_items(
|
|
224
|
+
module=module,
|
|
173
225
|
items=items,
|
|
174
|
-
absorb=absorb,
|
|
175
|
-
mdl_alias=mdl_alias,
|
|
176
226
|
caller_dir=caller_dir,
|
|
227
|
+
mod_bundle=valid_mod_bundle,
|
|
228
|
+
cachable=cachable,
|
|
229
|
+
lang=lng,
|
|
177
230
|
)
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
module = handle_directory(
|
|
183
|
-
module_name, path.splitext(full_target)[0], valid_mod_bundle
|
|
184
|
-
)
|
|
185
|
-
if items:
|
|
186
|
-
process_items(
|
|
187
|
-
module,
|
|
188
|
-
items,
|
|
189
|
-
caller_dir,
|
|
190
|
-
mod_bundle=valid_mod_bundle,
|
|
191
|
-
cachable=cachable,
|
|
192
|
-
)
|
|
193
|
-
else:
|
|
194
|
-
module = create_jac_py_module(
|
|
195
|
-
valid_mod_bundle, module_name, package_path, full_target
|
|
196
|
-
)
|
|
197
|
-
codeobj = get_codeobj(
|
|
198
|
-
full_target=full_target,
|
|
199
|
-
module_name=module_name,
|
|
200
|
-
mod_bundle=valid_mod_bundle,
|
|
201
|
-
cachable=cachable,
|
|
202
|
-
caller_dir=caller_dir,
|
|
203
|
-
)
|
|
204
|
-
try:
|
|
205
|
-
if not codeobj:
|
|
206
|
-
raise ImportError(f"No bytecode found for {full_target}")
|
|
207
|
-
with sys_path_context(caller_dir):
|
|
208
|
-
exec(codeobj, module.__dict__)
|
|
209
|
-
except Exception as e:
|
|
210
|
-
print(f"Error importing {full_target}: {str(e)}")
|
|
211
|
-
return None
|
|
212
|
-
return module
|
|
231
|
+
if items
|
|
232
|
+
else []
|
|
233
|
+
)
|
|
234
|
+
return (module,) if absorb or not items else tuple(unique_loaded_items)
|
|
213
235
|
|
|
214
236
|
|
|
215
237
|
def create_jac_py_module(
|
|
216
|
-
mod_bundle: Optional[Module
|
|
238
|
+
mod_bundle: Optional[Module],
|
|
217
239
|
module_name: str,
|
|
218
240
|
package_path: str,
|
|
219
241
|
full_target: str,
|
|
@@ -225,10 +247,18 @@ def create_jac_py_module(
|
|
|
225
247
|
module.__dict__["__jac_mod_bundle__"] = mod_bundle
|
|
226
248
|
if package_path:
|
|
227
249
|
parts = package_path.split(".")
|
|
250
|
+
base_path = full_target.split(package_path.replace(".", path.sep))[0]
|
|
228
251
|
for i in range(len(parts)):
|
|
229
252
|
package_name = ".".join(parts[: i + 1])
|
|
230
253
|
if package_name not in sys.modules:
|
|
231
|
-
|
|
254
|
+
full_mod_path = path.join(
|
|
255
|
+
base_path, package_name.replace(".", path.sep)
|
|
256
|
+
)
|
|
257
|
+
handle_directory(
|
|
258
|
+
module_name=package_name,
|
|
259
|
+
full_mod_path=full_mod_path,
|
|
260
|
+
mod_bundle=mod_bundle,
|
|
261
|
+
)
|
|
232
262
|
|
|
233
263
|
setattr(sys.modules[package_path], module_name, module)
|
|
234
264
|
sys.modules[f"{package_path}.{module_name}"] = module
|
|
@@ -253,12 +283,13 @@ def get_caller_dir(target: str, base_path: str, dir_path: str) -> str:
|
|
|
253
283
|
def py_import(
|
|
254
284
|
target: str,
|
|
255
285
|
caller_dir: str,
|
|
256
|
-
items: Optional[dict[str, Union[str,
|
|
286
|
+
items: Optional[dict[str, Union[str, Optional[str]]]] = None,
|
|
257
287
|
absorb: bool = False,
|
|
258
288
|
mdl_alias: Optional[str] = None,
|
|
259
|
-
) -> types.ModuleType:
|
|
289
|
+
) -> tuple[types.ModuleType, ...]:
|
|
260
290
|
"""Import a Python module."""
|
|
261
291
|
try:
|
|
292
|
+
loaded_items: list = []
|
|
262
293
|
if target.startswith("."):
|
|
263
294
|
target = target.lstrip(".")
|
|
264
295
|
full_target = path.normpath(path.join(caller_dir, target))
|
|
@@ -279,19 +310,25 @@ def py_import(
|
|
|
279
310
|
|
|
280
311
|
elif items:
|
|
281
312
|
for name, alias in items.items():
|
|
313
|
+
if isinstance(alias, bool):
|
|
314
|
+
alias = name
|
|
282
315
|
try:
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
alias if isinstance(alias, str) else name,
|
|
286
|
-
getattr(imported_module, name),
|
|
287
|
-
)
|
|
288
|
-
except AttributeError as e:
|
|
289
|
-
if hasattr(imported_module, "__path__"):
|
|
316
|
+
item = getattr(imported_module, name)
|
|
317
|
+
if item not in loaded_items:
|
|
290
318
|
setattr(
|
|
291
|
-
main_module,
|
|
292
|
-
alias if isinstance(alias, str) else name,
|
|
293
|
-
importlib.import_module(f"{target}.{name}"),
|
|
319
|
+
main_module, alias if isinstance(alias, str) else name, item
|
|
294
320
|
)
|
|
321
|
+
loaded_items.append(item)
|
|
322
|
+
except AttributeError as e:
|
|
323
|
+
if hasattr(imported_module, "__path__"):
|
|
324
|
+
item = importlib.import_module(f"{target}.{name}")
|
|
325
|
+
if item not in loaded_items:
|
|
326
|
+
setattr(
|
|
327
|
+
main_module,
|
|
328
|
+
alias if isinstance(alias, str) else name,
|
|
329
|
+
item,
|
|
330
|
+
)
|
|
331
|
+
loaded_items.append(item)
|
|
295
332
|
else:
|
|
296
333
|
raise e
|
|
297
334
|
|
|
@@ -301,7 +338,7 @@ def py_import(
|
|
|
301
338
|
mdl_alias if isinstance(mdl_alias, str) else target,
|
|
302
339
|
imported_module,
|
|
303
340
|
)
|
|
304
|
-
return imported_module
|
|
341
|
+
return (imported_module, *loaded_items)
|
|
342
|
+
|
|
305
343
|
except ImportError as e:
|
|
306
|
-
print(f"Failed to import module {target}")
|
|
307
344
|
raise e
|