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/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 module not in sys.modules:
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, bool]],
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
- ) -> None:
38
+ ) -> list:
37
39
  """Process items within a module by handling renaming and potentially loading missing attributes."""
38
- module_dir = (
39
- module.__path__[0]
40
- if hasattr(module, "__path__")
41
- else os.path.dirname(getattr(module, "__file__", ""))
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
- if alias and alias != name and not isinstance(alias, bool):
47
- setattr(module, alias, item)
52
+ handle_item_loading(item, alias)
48
53
  except AttributeError:
49
- jac_file_path = os.path.join(module_dir, f"{name}.jac")
50
- if hasattr(module, "__path__") and os.path.isfile(jac_file_path):
51
- item = load_jac_file(
52
- module=module,
53
- name=name,
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 item:
60
- setattr(module, name, item)
61
- if alias and alias != name and not isinstance(alias, bool):
62
- setattr(module, alias, item)
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, bool]]] = None,
142
- ) -> Optional[types.ModuleType]:
157
+ items: Optional[dict[str, Union[str, Optional[str]]]] = None,
158
+ ) -> tuple[types.ModuleType, ...]:
143
159
  """Core Import Process."""
144
- dir_path, file_name = path.split(
145
- path.join(*(target.split("."))) + (".jac" if lng == "jac" else ".py")
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
- return sys.modules[f"{package_path}.{module_name}"]
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
- return sys.modules[module_name]
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
- if lng == "py":
171
- module = py_import(
172
- target=target,
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
- else:
179
- module_name = override_name if override_name else module_name
180
-
181
- if os.path.isdir(path.splitext(full_target)[0]):
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 | str],
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
- sys.modules[package_name] = types.ModuleType(package_name)
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, bool]]] = None,
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
- setattr(
284
- main_module,
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