def _test_dependencies(self): """ Check all target programming and operating system dependencies. """ lang = self.target_language if sys.platform in ('cygwin', 'win32', 'win64'): error = "The required dependencies aren't available on Windows." raise EnvironmentError(error) # Dependencies: depends = { 'c': ['gcc'], 'java': ['java', 'javac'], 'js': ['node'], 'go': ['go'], 'php': ['php'], 'ruby': ['ruby'] } all_depends = depends.get(lang) + ['mkdir', 'rm'] all_depends = [str(e) for e in all_depends] cmd = 'if hash {} 2/dev/null; then echo 1; else echo 0; fi' for exe in all_depends: cmd = cmd.format(exe) status = Shell.check_output(cmd) if sys.version_info >= (3, 3) and isinstance(status, bytes): status = status.decode('utf-8') status = str(status).strip() if status != '1': error = "The required application '{0}'" \ " isn't available.".format(exe) raise SystemError(error)
def pred_in_custom(self, features, cast=True): # $ ./<temp_filename> <features> cmd = [os.path.join('.', 'tmp', self.tmp_fn)] args = [str(f).strip() for f in features] cmd += args pred = Shell.check_output(cmd) return int(pred) if cast else float(pred)
def pred_in_custom(self, features, cast=True, export_data=False): cmd = ['node', self.tmp_fn] if export_data: cmd += ['http://0.0.0.0:8713/tmp/data.json'] args = [str(f).strip() for f in features] cmd += args pred = Shell.check_output(cmd) return int(pred) if cast else float(pred)
def pred_in_custom(self, features, cast=True): # $ ruby temp <temp_filename> <features> filename = self.tmp_fn + '.rb' path = os.path.join('tmp', filename) cmd = ['ruby', path] args = [str(f).strip() for f in features] cmd += args pred = Shell.check_output(cmd) return int(pred) if cast else float(pred)
def pred_in_custom(self, features, cast=True): # $ php -f <tmp_filename> <features> filename = self.tmp_fn + '.php' path = os.path.join('tmp', filename) cmd = 'php -f {}'.format(path).split() args = [str(f).strip() for f in features] cmd += args pred = Shell.check_output(cmd) return int(pred) if cast else float(pred)
def pred_in_custom(self, features, cast=True, export_data=False): if export_data: cmd = 'java -cp ./gson.jar:./tmp {}'.format(self.tmp_fn).split() cmd += ['./tmp/data.json'] else: cmd = 'java -classpath tmp {}'.format(self.tmp_fn).split() args = [str(f).strip() for f in features] cmd += args pred = Shell.check_output(cmd) return int(pred) if cast else float(pred)
def predict(self, X, class_name=None, method_name=None, tnp_dir='tmp', keep_tmp_dir=False, num_format=lambda x: str(x)): """ Predict using the transpiled model. Parameters ---------- :param X : {array-like}, shape (n_features) or (n_samples, n_features) The input data. :param class_name : string, default: None The name for the ported class. :param method_name : string, default: None The name for the ported method. :param tnp_dir : string, default: 'tmp' The path to the temporary directory for storing the transpiled (and compiled) model. :param keep_tmp_dir : bool, default: False Whether to delete the temporary directory or not. :param num_format : lambda x, default: lambda x: str(x) The representation of the floating-point values. Returns ------- y : int or array-like, shape (n_samples,) The predicted class or classes. """ if class_name is None: class_name = self.estimator_name if method_name is None: method_name = self.target_method # Dependencies: if not self._tested_dependencies: self._test_dependencies() self._tested_dependencies = True # Support: if 'predict' not in set(self.template.SUPPORTED_METHODS): error = "Currently the given model method" \ " '{}' isn't supported.".format('predict') raise AttributeError(error) # Cleanup: Shell.call('rm -rf {}'.format(tnp_dir)) Shell.call('mkdir {}'.format(tnp_dir)) # Transpiled model: details = self.export(class_name=class_name, method_name=method_name, num_format=num_format, details=True) filename = Porter._get_filename(class_name, self.target_language) target_file = os.path.join(tnp_dir, filename) with open(target_file, str('w')) as file_: file_.write(details.get('estimator')) # Compilation command: comp_cmd = details.get('cmd').get('compilation') if comp_cmd is not None: Shell.call(comp_cmd, cwd=tnp_dir) # Execution command: exec_cmd = details.get('cmd').get('execution') exec_cmd = str(exec_cmd).split() pred_y = None # Single feature set: if exec_cmd is not None and len(X.shape) == 1: full_exec_cmd = exec_cmd + [str(sample).strip() for sample in X] pred_y = Shell.check_output(full_exec_cmd, cwd=tnp_dir) pred_y = int(pred_y) # Multiple feature sets: if exec_cmd is not None and len(X.shape) > 1: pred_y = np.empty(X.shape[0], dtype=int) for idx, features in enumerate(X): full_exec_cmd = exec_cmd + [str(f).strip() for f in features] pred = Shell.check_output(full_exec_cmd, cwd=tnp_dir) pred_y[idx] = int(pred) # Cleanup: if not keep_tmp_dir: Shell.call('rm -rf {}'.format(tnp_dir)) return pred_y
def test_check_output_echo_num_0(self): self.assertEqual(Shell.check_output('echo 0'), '0')
def test_check_output_empty_text(self): self.assertRaises(AttributeError, lambda: Shell.check_output(''))
def test_check_output_echo_list_xyz(self): self.assertEqual(Shell.check_output(['echo', 'xyz'], shell=False), 'xyz')
def test_check_output_echo_num_1(self): self.assertEqual(Shell.check_output('echo 1'), '1')