Conditions | 10 |
Total Lines | 102 |
Lines | 0 |
Ratio | 0 % |
Changes | 1 | ||
Bugs | 0 | Features | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like PythonRunner.run() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | # Licensed to the StackStorm, Inc ('StackStorm') under one or more |
||
109 | def run(self, action_parameters): |
||
110 | LOG.debug('Running pythonrunner.') |
||
111 | LOG.debug('Getting pack name.') |
||
112 | pack = self.get_pack_ref() |
||
113 | pack_db = Pack.get_by_ref(pack) |
||
114 | LOG.debug('Getting user.') |
||
115 | user = self.get_user() |
||
116 | LOG.debug('Serializing parameters.') |
||
117 | serialized_parameters = json.dumps(action_parameters) if action_parameters else '' |
||
118 | LOG.debug('Getting virtualenv_path.') |
||
119 | virtualenv_path = get_sandbox_virtualenv_path(pack=pack) |
||
120 | LOG.debug('Getting python path.') |
||
121 | if self._sandbox: |
||
122 | python_path = get_sandbox_python_binary_path(pack=pack) |
||
123 | else: |
||
124 | python_path = sys.executable |
||
125 | |||
126 | LOG.debug('Checking virtualenv path.') |
||
127 | if virtualenv_path and not os.path.isdir(virtualenv_path): |
||
128 | format_values = {'pack': pack, 'virtualenv_path': virtualenv_path} |
||
129 | msg = PACK_VIRTUALENV_DOESNT_EXIST % format_values |
||
130 | LOG.error('virtualenv_path set but not a directory: %s', msg) |
||
131 | raise Exception(msg) |
||
132 | |||
133 | LOG.debug('Checking entry_point.') |
||
134 | if not self.entry_point: |
||
135 | LOG.error('Action "%s" is missing entry_point attribute' % (self.action.name)) |
||
136 | raise Exception('Action "%s" is missing entry_point attribute' % (self.action.name)) |
||
137 | |||
138 | # Note: We pass config as command line args so the actual wrapper process is standalone |
||
139 | # and doesn't need access to db |
||
140 | LOG.debug('Setting args.') |
||
141 | args = [ |
||
142 | python_path, |
||
143 | '-u', # unbuffered mode so streaming mode works as expected |
||
144 | WRAPPER_SCRIPT_PATH, |
||
145 | '--pack=%s' % (pack), |
||
146 | '--file-path=%s' % (self.entry_point), |
||
147 | '--parameters=%s' % (serialized_parameters), |
||
148 | '--user=%s' % (user), |
||
149 | '--parent-args=%s' % (json.dumps(sys.argv[1:])), |
||
150 | ] |
||
151 | |||
152 | if self._config: |
||
153 | args.append('--config=%s' % (json.dumps(self._config))) |
||
154 | |||
155 | if self._log_level != 'debug': |
||
156 | # We only pass --log-level parameter if non default log level value is specified |
||
157 | args.append('--log-level=%s' % (self._log_level)) |
||
158 | |||
159 | # We need to ensure all the st2 dependencies are also available to the |
||
160 | # subprocess |
||
161 | LOG.debug('Setting env.') |
||
162 | env = os.environ.copy() |
||
163 | env['PATH'] = get_sandbox_path(virtualenv_path=virtualenv_path) |
||
164 | |||
165 | sandbox_python_path = get_sandbox_python_path(inherit_from_parent=True, |
||
166 | inherit_parent_virtualenv=True) |
||
167 | pack_common_libs_path = get_pack_common_libs_path(pack_db=pack_db) |
||
168 | |||
169 | if self._enable_common_pack_libs and pack_common_libs_path: |
||
170 | env['PYTHONPATH'] = pack_common_libs_path + ':' + sandbox_python_path |
||
171 | else: |
||
172 | env['PYTHONPATH'] = sandbox_python_path |
||
173 | |||
174 | # Include user provided environment variables (if any) |
||
175 | user_env_vars = self._get_env_vars() |
||
176 | env.update(user_env_vars) |
||
177 | |||
178 | # Include common st2 environment variables |
||
179 | st2_env_vars = self._get_common_action_env_variables() |
||
180 | env.update(st2_env_vars) |
||
181 | datastore_env_vars = self._get_datastore_access_env_vars() |
||
182 | env.update(datastore_env_vars) |
||
183 | |||
184 | stdout = StringIO() |
||
185 | stderr = StringIO() |
||
186 | |||
187 | store_execution_stdout_line = functools.partial(store_execution_output_data, |
||
188 | output_type='stdout') |
||
189 | store_execution_stderr_line = functools.partial(store_execution_output_data, |
||
190 | output_type='stderr') |
||
191 | |||
192 | read_and_store_stdout = make_read_and_store_stream_func(execution_db=self.execution, |
||
193 | action_db=self.action, store_data_func=store_execution_stdout_line) |
||
194 | read_and_store_stderr = make_read_and_store_stream_func(execution_db=self.execution, |
||
195 | action_db=self.action, store_data_func=store_execution_stderr_line) |
||
196 | |||
197 | command_string = list2cmdline(args) |
||
198 | LOG.debug('Running command: PATH=%s PYTHONPATH=%s %s' % (env['PATH'], env['PYTHONPATH'], |
||
199 | command_string)) |
||
200 | exit_code, stdout, stderr, timed_out = run_command(cmd=args, stdout=subprocess.PIPE, |
||
201 | stderr=subprocess.PIPE, shell=False, |
||
202 | env=env, |
||
203 | timeout=self._timeout, |
||
204 | read_stdout_func=read_and_store_stdout, |
||
205 | read_stderr_func=read_and_store_stderr, |
||
206 | read_stdout_buffer=stdout, |
||
207 | read_stderr_buffer=stderr) |
||
208 | LOG.debug('Returning values: %s, %s, %s, %s' % (exit_code, stdout, stderr, timed_out)) |
||
209 | LOG.debug('Returning.') |
||
210 | return self._get_output_values(exit_code, stdout, stderr, timed_out) |
||
211 | |||
348 |