Skip to content

Commit 6cc6b6a

Browse files
authored
Json work (#12)
* Move operations into their own directory * Fix kwarg problem in wrapping commands * preload_updates Now saves a modules.json file with saved contexts Will automatically use the modules file in the save model if one is not provided * Added null option If module_path is null, will skip loading modules.json
1 parent 1158e43 commit 6cc6b6a

File tree

4 files changed

+99
-22
lines changed

4 files changed

+99
-22
lines changed

ngcsimlib/__init__.py

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,31 @@
66
from types import SimpleNamespace
77
from importlib import import_module
88
from ngcsimlib.configManager import init_config, get_config
9-
9+
from ngcsimlib.logger import warn
1010
from pkg_resources import get_distribution
1111

1212
__version__ = get_distribution('ngcsimlib').version ## set software version
1313

1414

1515
###### Preload Modules
16-
def preload_modules():
17-
module_config = get_config("modules")
18-
if module_config is None:
19-
module_path = "json_files/modules.json"
16+
def preload_modules(path=None):
17+
if path is None:
18+
module_config = get_config("modules")
19+
if module_config is None:
20+
module_path = "json_files/modules.json"
21+
else:
22+
module_path = module_config.get("module_path", "json_files/modules.json")
23+
24+
if module_path is None:
25+
return
26+
27+
if not os.path.isfile(module_path):
28+
warn("Missing file to preload modules from. Attempted to locate file at \"" + str(module_path) +
29+
"\". No modules will be preloaded. "
30+
"\nSee https://ngc-learn.readthedocs.io/en/latest/tutorials/model_basics/json_modules.html for additional information")
31+
return
2032
else:
21-
module_path = module_config.get("module_path", "json_files/modules.json")
22-
23-
if not os.path.isfile(module_path):
24-
warnings.warn("\nMissing file to preload modules from. Attempted to locate file at \"" + str(module_path) +
25-
"\". No modules will be preloaded. "
26-
"\nSee https://ngc-learn.readthedocs.io/en/latest/tutorials/model_basics/json_modules.html for additional information")
27-
return
33+
module_path = path
2834

2935
with open(module_path, 'r') as file:
3036
modules = json.load(file, object_hook=lambda d: SimpleNamespace(**d))
@@ -42,6 +48,7 @@ def preload_modules():
4248
for keyword in attribute.keywords:
4349
utils._Loaded_Attributes[keyword] = atr
4450

51+
utils.set_loaded(True)
4552

4653
###### Initialize Config
4754
def configure():
@@ -59,7 +66,7 @@ def configure():
5966
config_path = "json_files/config.json"
6067

6168
if not os.path.isfile(config_path):
62-
warnings.warn("\nMissing configuration file. Attempted to locate file at \"" + str(config_path) +
69+
warn("Missing configuration file. Attempted to locate file at \"" + str(config_path) +
6370
"\". Default Config will be used. "
6471
"\nSee https://ngc-learn.readthedocs.io/en/latest/tutorials/model_basics/configuration.html for "
6572
"additional information")

ngcsimlib/commands/clamp.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def __init__(self, components=None, compartment=None, clamp_name=None,
4141
for name, component in self.components.items():
4242
mapped = hasattr(component, self.compartment)
4343
if mapped:
44-
if Compartment.is_compartment(getattr(compartment, self.compartment)):
44+
if Compartment.is_compartment(getattr(component, self.compartment)):
4545
continue
4646

4747
error(self.name, " is attempting to initialize clamp to non-existent compartment \"",

ngcsimlib/context.py

Lines changed: 70 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from ngcsimlib.utils import make_unique_path, check_attributes, check_serializable, load_from_path
22
from ngcsimlib.logger import warn, info
33
from ngcsimlib.utils import get_compartment_by_name, \
4-
get_context, add_context, get_current_path, get_current_context, set_new_context
4+
get_context, add_context, get_current_path, get_current_context, set_new_context, load_module, is_pre_loaded
5+
from ngcsimlib import preload_modules
56
from ngcsimlib.compilers.command_compiler import dynamic_compile, wrap_command
67
import json, os
78

@@ -75,13 +76,15 @@ def __exit__(self, exc_type, exc_val, exc_tb):
7576
"""
7677
set_new_context(self._last_context)
7778

78-
def get_components(self, *component_names):
79+
def get_components(self, *component_names, unwrap=True):
7980
"""
8081
Gets all the components by name in a context
8182
8283
Args:
8384
component_names: an arbitrary list of component names to get
8485
86+
unwrap: return just the component not a list of length 1 if only a single component is retrieved
87+
8588
Returns:
8689
either a list of components or a single component depending on the number of components being retrieved
8790
"""
@@ -93,7 +96,7 @@ def get_components(self, *component_names):
9396
_components.append(self.components[a])
9497
else:
9598
warn(f"Could not fine a component with the name \"{a}\" in the context")
96-
return _components if len(component_names) > 1 else _components[0]
99+
return _components if len(component_names) > 1 or not unwrap else _components[0]
97100

98101
def register_op(self, op):
99102
"""
@@ -119,7 +122,7 @@ def register_command(self, klass, *args, components=None, command_name=None, **k
119122
120123
kwargs: the keyword arguments passed into the command
121124
"""
122-
_components = [components.name for components in components]
125+
_components = [component.name for component in components]
123126
self._json_objects['commands'][command_name] = {"class": klass, "components": _components, "args": args,
124127
"kwargs": kwargs}
125128

@@ -208,6 +211,9 @@ def save_to_json(self, directory, model_name=None, custom_save=True):
208211
"""
209212
path = make_unique_path(directory, model_name)
210213

214+
with open(path + "/modules.json", "w") as fp:
215+
json.dump(self.make_modules(), fp, indent=4)
216+
211217
with open(path + "/ops.json", 'w') as fp:
212218
json.dump(self._json_objects['ops'], fp, indent=4)
213219

@@ -278,6 +284,11 @@ def load_from_dir(self, directory, custom_folder="/custom"):
278284
custom_folder: The name of the custom data folder for building
279285
components. (Default: `/custom`)
280286
"""
287+
288+
if os.path.isfile(directory + "/modules.json") and not is_pre_loaded():
289+
info("No modules file loaded, loading from model directory")
290+
preload_modules(path=directory + "/modules.json")
291+
281292
self.make_components(directory + "/components.json", directory + custom_folder)
282293
self.make_ops(directory + "/ops.json")
283294
self.make_commands(directory + "/commands.json")
@@ -345,14 +356,15 @@ def make_commands(self, path_to_commands_file):
345356
if command['class'] == "dynamic_compiled":
346357
if len(command['components']) > 1:
347358
self.compile_by_key(
348-
*self.get_components(*command['components']), compile_key=command['compile_key'], name=c_name)
359+
*self.get_components(*command['components'], unwrap=False), compile_key=command['compile_key'],
360+
name=c_name)
349361
else:
350362
self.compile_by_key(
351-
self.get_components(*command['components']), compile_key=command['compile_key'],
363+
self.get_components(*command['components'], unwrap=False), compile_key=command['compile_key'],
352364
name=c_name)
353365
else:
354366
klass = load_from_path(command['class'])
355-
klass(*command['args'], **command['kwargs'], components=self.get_components(*command['components']),
367+
klass(*command['args'], **command['kwargs'], components=self.get_components(*command['components'], unwrap=False),
356368
command_name=c_name)
357369

358370
def _make_op(self, op_spec):
@@ -425,3 +437,54 @@ def wrap_and_add_command(self, command, name=None):
425437
name: The name of the command (default: None)
426438
"""
427439
self.add_command(wrap_command(command), name=name)
440+
441+
def make_modules(self):
442+
modules = {}
443+
jComponents = self._json_objects['components']
444+
for c_path, c in jComponents.items():
445+
mod = load_module(c["class"]).__name__
446+
447+
module = ".".join(mod.split(".")[:-1])
448+
klass = c["class"]
449+
450+
if module not in modules.keys():
451+
modules[module] = {"attributes": []}
452+
453+
if klass not in map(lambda x: x["name"], modules[module]["attributes"]):
454+
modules[module]["attributes"].append({"name": klass})
455+
456+
jOperators = self._json_objects['ops']
457+
for o in jOperators:
458+
mod = load_module(o["class"]).__name__
459+
460+
module = ".".join(mod.split(".")[:-1])
461+
klass = o["class"]
462+
463+
if module not in modules.keys():
464+
modules[module] = {"attributes": []}
465+
466+
if klass not in map(lambda x: x["name"], modules[module]["attributes"]):
467+
modules[module]["attributes"].append({"name": klass})
468+
469+
470+
jCommands = self._json_objects['commands']
471+
for c_name, c in jCommands.items():
472+
if c["class"] == "dynamic_compiled":
473+
continue
474+
475+
mod = load_module(c["class"]).__name__
476+
477+
module = ".".join(mod.split(".")[:-1])
478+
klass = c["class"]
479+
480+
if module not in modules.keys():
481+
modules[module] = {"attributes": []}
482+
483+
if klass not in map(lambda x: x["name"], modules[module]["attributes"]):
484+
modules[module]["attributes"].append({"name": klass})
485+
486+
_modules = []
487+
for key, value in modules.items():
488+
_modules.append({"absolute_path": key, "attributes": value["attributes"]})
489+
490+
return _modules

ngcsimlib/utils.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,18 @@
33
"""
44
import sys, uuid, os, json
55
from importlib import import_module
6+
from ngcsimlib.logger import info
67

78
## Globally tracking all the modules, and attributes have been dynamically loaded
89
_Loaded_Attributes = {}
910
_Loaded_Modules = {}
11+
_Loaded = False
12+
def is_pre_loaded():
13+
return _Loaded
1014

15+
def set_loaded(val):
16+
global _Loaded
17+
_Loaded = val
1118

1219
def check_attributes(obj, required, fatal=False):
1320
"""
@@ -68,7 +75,7 @@ def load_module(module_path, match_case=False, absolute_path=False):
6875
last_mod = module.split('.')[-1]
6976
last_mod = last_mod if match_case else last_mod.lower()
7077
if final_mod == last_mod:
71-
print("Loading module from " + module)
78+
info("Loading module from " + module)
7279
module_name = module
7380
break
7481

0 commit comments

Comments
 (0)