66from ngcsimlib .utils import get_current_context , infer_context , Set_Compartment_Batch
77
88class 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
79193def 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
0 commit comments