Skip to content

Commit 18b7c45

Browse files
committed
Added comments to new methods
1 parent bd55f1f commit 18b7c45

File tree

4 files changed

+197
-6
lines changed

4 files changed

+197
-6
lines changed

ngcsimlib/compilers/process.py

Lines changed: 138 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,44 @@
66
from ngcsimlib.utils import get_current_context, infer_context, Set_Compartment_Batch
77

88
class Process(object):
9+
"""
10+
The process is an alternate method for compiling transitions of models into
11+
pure methods. In general this is the preferred method for doing this over
12+
the legacy compiler, however it is not required. The Process composes the
13+
methods used as they are added to the process meaning that partial compiling
14+
is possible for debugging by stopping adding to the chain of transitions in
15+
the process.
16+
17+
The general use case to create a process is as follows
18+
myProcess = (Process("myProcess")
19+
>> myFirstComponent.firstTransition
20+
>> myFirstComponent.secondTransition
21+
>> mySecondComponent.firstTransition
22+
>> mySecondComponent.secondTransition)
23+
24+
However, the adding of new methods does not need to happen only at the
25+
initialization of the Process class. The above example can be added to as
26+
follows:
27+
myProcess >> myThirdComponent.firstTransition
28+
myProcess >> myThirdComponent.secondTransition
29+
30+
In general once all the transition methods are added to the process there
31+
are two ways of actually running the transitions defined in the process.
32+
The first is through the use of myProcess.pure(current_state, **kwargs) this
33+
executes the process as a pure method doing nothing to update the actual
34+
state of the model.
35+
36+
The other method for running a process is through
37+
myProcess.execute(**kwargs). This runs the process with the current state of
38+
the model. By default, this also does not update the model with the final
39+
state, however this can be changed with the flag "update_state".
40+
"""
941
def __init__(self, name):
42+
"""
43+
Creates and empty process using the provided name
44+
Args:
45+
name: the name of the process (should be unique per context)
46+
"""
1047
self._method = None
1148
self._calls = []
1249
self.name = name
@@ -19,6 +56,17 @@ def __init__(self, name):
1956

2057
@staticmethod
2158
def make_process(process_spec, custom_process_klass=None):
59+
"""
60+
Used the in the creation of a process from a json file. Under normal
61+
circumstances this is not normally called by the user.
62+
63+
Args:
64+
process_spec: the parsed json object to create a process from
65+
custom_process_klass: a custom subclass of a process to build
66+
67+
Returns: the created process
68+
69+
"""
2270
if custom_process_klass is None:
2371
custom_process_klass = Process
2472
newProcess = custom_process_klass(process_spec['name'])
@@ -32,12 +80,32 @@ def make_process(process_spec, custom_process_klass=None):
3280

3381
@property
3482
def pure(self):
83+
"""
84+
Returns: The current compile method for the process as a pure method
85+
"""
3586
return self._method
3687

3788
def __rshift__(self, other):
89+
"""
90+
Added wrapper for the transition method
91+
Args:
92+
other: the transition call for the transition method
93+
94+
Returns: the process for the use of chaining calls
95+
"""
3896
return self.transition(other)
3997

4098
def transition(self, transition_call):
99+
"""
100+
Adds the given transition call to the Process. The argument call must be
101+
decorated by the @transition decorator.
102+
103+
Args:
104+
transition_call: Transition method to add to the process
105+
106+
Returns: the process for the use of chaining calls
107+
108+
"""
41109
self._calls.append({"path": transition_call.__self__.path, "key": transition_call.resolver_key})
42110
self._needed_contexts.add(infer_context(transition_call.__self__.path))
43111
new_step, new_args = compile_component(transition_call)
@@ -48,6 +116,23 @@ def transition(self, transition_call):
48116
return self
49117

50118
def execute(self, update_state=False, **kwargs):
119+
"""
120+
Executes the process using the current state of the model to run. This
121+
method has checks to ensure that the process has transitions added to it
122+
as well as that all the keyword arguments required by each of the
123+
transition call are in the provided keyword arguments. By default, this
124+
does not update the final state of the model but that can be toggled
125+
with the flag "update_state".
126+
127+
Args:
128+
update_state: Should this method update the final state of the model
129+
**kwargs: The required keyword arguments to execute the process
130+
131+
Returns: the final state of the process regardless of the model is
132+
updated to reflect this. Will return null if either of the above checks
133+
fail
134+
135+
"""
51136
if self._method is None:
52137
warn("Attempting to execute a process with no transition steps")
53138
return
@@ -61,25 +146,77 @@ def execute(self, update_state=False, **kwargs):
61146
return state
62147

63148
def as_obj(self):
149+
"""
150+
Returns: Returns this process as an object to be used with json files
151+
"""
64152
return {"name": self.name, "class": self.__class__.__name__, "calls": self._calls}
65153

66154
def get_required_args(self):
155+
"""
156+
Returns: The needed arguments for all the transition calls in this
157+
process as a set
158+
"""
67159
return self._needed_args
68160

69161
def get_required_state(self, include_special_compartments=False):
162+
"""
163+
Gets the required compartments needed to run this process, important to
164+
note that if this is going to be used as an argument to the pure method
165+
make sure that the "include_special_compartments" flag is set to True so
166+
that special compartments found in certain components are visible.
167+
Args:
168+
include_special_compartments: A flag to show the compartments that
169+
denoted as special compartments by ngcsimlib (this is any
170+
compartment with * in their name, these are can only be created
171+
dynamically)
172+
173+
Returns: A subset of the model state based on the required compartments
174+
175+
"""
70176
compound_state = {}
71177
for context in self._needed_contexts:
72178
compound_state.update(context.get_current_state(include_special_compartments))
73179
return compound_state
74180

75181
def updated_modified_state(self, state):
182+
"""
183+
Updates the model with the provided state. It is important to note that
184+
only values that are rquired for the execution of this process will be
185+
affected by this call. If all compartments need to be updated, view
186+
other options found in ngcsimlib.utils.
187+
Args:
188+
state: The state to update the model with
189+
"""
76190
Set_Compartment_Batch({key: value for key, value in state.items() if key in self.get_required_state(include_special_compartments=True)})
77191

78192

79193
def transition(output_compartments, builder=False):
194+
"""
195+
The decorator to be paired with the Process call. This method does
196+
everything that the now outdated resolver did to ensure backward
197+
compatability. This decorator expects to decorate a static method on a
198+
class.
199+
200+
Through normal patterns these decorated method will never be directly called
201+
by the end user, but if they are for the purpose of debugging there are a
202+
few things to keep in mind. While the process compiler will automatically
203+
link values in the component to the different values to be passed into the
204+
method that does not exist if they are directly called. In addition, if the
205+
method is going to be called at a class level the first value passed into
206+
the method must be None to not mess up the internal decoration.
207+
Args:
208+
output_compartments: The string name of the output compartments the
209+
outputs of this method will be assigned to in the order they are output.
210+
builder: A boolean flag for if this method is a builder method for the
211+
compiler. A builder method is a method that returns the static method to
212+
use in the transition.
213+
214+
Returns: the wrapped method
215+
216+
"""
80217
def _wrapper(f):
81218
@wraps(f)
82-
def inner(*args, **kwargs):
219+
def inner(self, *args, **kwargs):
83220
return f(*args, **kwargs)
84221

85222

ngcsimlib/compilers/process_compiler/component_compiler.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
"""
2+
This file contains the methods used to compile methods for the use of Processes.
3+
The general methodology behind this compiler is that if all transitions can be
4+
expressed as f(current_state, **kwargs) -> final_state they can then be composed
5+
together as f(g(current_state, **kwargs) **kwargs) -> final_state. While it is
6+
technically possible to use the compiler outside the process its intended use
7+
case is through the process and thus if error occur though other uses support
8+
may be minimal.
9+
"""
10+
111
from ngcsimlib.compilers.process_compiler.op_compiler import compile as op_compile
212
from ngcsimlib.compartment import Compartment
313
from ngcsimlib.compilers.utils import compose
@@ -11,19 +21,31 @@ def __make_get_param(p, component):
1121
def __make_get_comp(c, component):
1222
return lambda current_state, **kwargs: current_state.get(component.__dict__[c].path, None)
1323

14-
def builder(transition_method_to_build):
24+
def _builder(transition_method_to_build):
1525
component = transition_method_to_build.__self__
1626
builder_method = transition_method_to_build.f
1727
# method, output_compartments, args, params, input_compartments
1828
return builder_method(component)
1929

2030

2131
def compile(transition_method):
32+
"""
33+
This method is the main compile method for the process compiler. Unlike the
34+
legacy compiler this compiler is designed to be self-contained and output
35+
the methods that are composed together to make the process compiler function
36+
Args:
37+
transition_method: a method usually component.method that has been
38+
decorated by the @transition decorator.
39+
40+
Returns: the pure compiled method of the form
41+
f(current_state, **kwargs) -> final_state)
42+
43+
"""
2244
composition = None
2345
component = transition_method.__self__
2446

2547
if transition_method.builder:
26-
pure_fn, output, args, parameters, compartments = builder(transition_method)
48+
pure_fn, output, args, parameters, compartments = _builder(transition_method)
2749
else:
2850

2951
pure_fn = transition_method.f

ngcsimlib/compilers/process_compiler/op_compiler.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ def _make_lambda(s):
55

66
def compile(op):
77
"""
8-
compiles the operation down to its execution order
8+
compiles root operation down to a single method of
9+
f(current_state, **kwargs) -> final_state
910
1011
Args:
1112
op: the operation to compile
1213
13-
Returns:
14-
the execution order needed to run this operation compiled
14+
Returns: the compiled operation
1515
"""
1616
arg_methods = []
1717
for s in op.sources:

ngcsimlib/context.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,14 @@ def register_component(self, component, *args, **kwargs):
207207
self._json_objects['components'][c_path] = obj
208208

209209
def register_process(self, process):
210+
"""
211+
Adds a process to the list of processes to be saved by the context.
212+
Unlike with the other saved parts of the context the actual json objects
213+
for the processes have to be calculated as time of save since they are
214+
constantly changing.
215+
Args:
216+
process: The process to add
217+
"""
210218
self._json_objects['processes'].append(process)
211219

212220
def add_component(self, component):
@@ -476,6 +484,11 @@ def _make_op(self, op_spec):
476484
dest << obj
477485

478486
def make_process(self, path_to_process_file):
487+
"""
488+
Will load the processes saved in the provided json file into the model
489+
Args:
490+
path_to_process_file: the path to the saved json file
491+
"""
479492
with open(path_to_process_file, 'r') as file:
480493
process_spec = json.load(file)
481494
for p in process_spec:
@@ -666,8 +679,27 @@ def _get_state_keys(self, include_special_compartments=False):
666679
return all_keys
667680

668681
def get_current_state(self, include_special_compartments=False):
682+
"""
683+
Get the current state of the model based on the components found in this
684+
context.
685+
Args:
686+
include_special_compartments: Should this method include
687+
compartments denotes as special compartments by ngcsimlib. These are
688+
all compartments that include * in their path. (Only creatable
689+
dynamically)
690+
691+
Returns: All the compartments found in this context.
692+
693+
"""
669694
return Get_Compartment_Batch(self._get_state_keys(include_special_compartments))
670695

671696
def update_current_state(self, state):
697+
"""
698+
Updates the compartments found in this context. While this method can
699+
take a model state that includes compartments from other contexts it
700+
will only update the compartments found in this context.
701+
Args:
702+
state: The state to update the model to
703+
"""
672704
Set_Compartment_Batch({key: value for key, value in state.items() if key in self._get_state_keys()})
673705

0 commit comments

Comments
 (0)