{"action":"created","comment":{"url":"https://api.github.com/repos/boutiques/tools/pulls/comments/70791469","id":70791469,"diff_hunk":"@@ -0,0 +1,424 @@\n+#!/usr/bin/env python\n+\n+'''\n+A local tool executor to help test JSON descriptors for use in the Boutiques framework.\n+Should be used after successfully running validator.rb.\n+\n+Program flow:\n+  - Requires a JSON descriptor of the tool, following the Boutiques schema.\n+  - Requires an input set of parameters. Can either:\n+    o Come from a .json file or .csv file [Specfied by --input/-i]\n+    o Be randomly generated based on the input json descriptor [Specified by --random/-r]\n+  - The tool can then either:\n+    o Print the resulting command-line based on the input (to help check correctness of the permitted command lines) [Default behaviour]\n+    o Attempt to execute the command line output by the tool, for the given parameters (not for the random case) [--exec/-e flag]\n+\n+Note: validating the schema with a validator is recommended first. This script does not check the descriptor with respect to the schema.\n+      Only in the -e case are output files checked for, at the end\n+\n+Formats:\n+A .json input file should look like:\n+{\n+  \"inputs\" : [\n+    { \"input_id_1\" : \"val1\" },\n+    { \"input_id_2\" : \"val2\" },\n+    ...\n+  ]\n+}\n+\n+A .csv input file should look like:\n+input_id_1,val1\n+input_id_2,val2\n+...\n+\n+A string input should look like:\n+python localExec.py desc.json -s 'in_id_1,val_1;in_id_2,val_2;...'\n+\n+Notes: pass lists by space-separated values [cannot be passed by --string]\n+       pass flags with 'true' or 'false' (false is the same as not including it)\n+\n+'''\n+\n+import argparse, os, sys, json, random as rnd, string, math, subprocess, time\n+\n+# Executor class\n+class LocalExecutor(object):\n+\n+  # Constructor\n+  def __init__(self,desc):\n+    self.desc_path = desc  # Save descriptor path\n+    self.errs      = []    # Empty errors holder\n+    self.debug     = False # debug mode (also use python -u for unbuffered printing)\n+    # Parse JSON descriptor\n+    with open(desc, 'r') as descriptor:\n+      self.desc_dict = json.loads( descriptor.read() )\n+    # Helpers\n+    self.inputs     = self.desc_dict['inputs'] # Structure: [ {id:...},...,{id:...} ]\n+    self.groups     = self.desc_dict['groups'] if 'groups' in self.desc_dict.keys() else []\n+    self.byId       = lambda n: [ v for v in self.inputs if v['id']==n][0]\n+    self.byGid      = lambda g: [ v for v in self.groups if v['id']==g][0]\n+    self.safeGet    = lambda i,k: None if not k in self.byId(i).keys() else self.byId(i)[k]\n+    self.safeGrpGet = lambda g,k: None if not k in self.byGid(g).keys() else self.byGid(g)[k]\n+    self.assocGrp   = lambda i: (filter( lambda g: i in g[\"members\"], self.groups ) or [None])[0]\n+    self.reqsOf     = lambda t: self.safeGet(t,\"requires-inputs\") or []\n+\n+  # Attempt execution\n+  def execute(self):\n+    command = self.cmdLine[0]\n+    print('Attempting execution of command:\\n\\t' + command + '\\n---/* Start program output */---')\n+    # Run command\n+    try:\n+      # Note: invokes the command through the shell (potential injection dangers)\n+      process = subprocess.Popen( command , shell=True )\n+    except OSError as e:\n+      sys.stderr.write( 'OS Error during attempted execution!' )\n+      raise e\n+    except ValueError as e:\n+      sys.stderr.write( 'Input Value Error during attempted execution!' )\n+      raise e\n+    else:\n+      exit_code = process.wait()\n+      # Report exit status\n+      print('---/* End program output */---\\nCompleted execution (exit code: ' + str(exit_code) + ')')\n+      time.sleep(0.5) # Give the OS a (half) second to finish writing","path":"localExec.py","position":83,"original_position":83,"commit_id":"dc15bb8291f372abce8e434b29f095ae8b534269","original_commit_id":"dc15bb8291f372abce8e434b29f095ae8b534269","user":{"login":"glatard","id":5174953,"avatar_url":"https://avatars.githubusercontent.com/u/5174953?v=3","gravatar_id":"","url":"https://api.github.com/users/glatard","html_url":"https://github.com/glatard","followers_url":"https://api.github.com/users/glatard/followers","following_url":"https://api.github.com/users/glatard/following{/other_user}","gists_url":"https://api.github.com/users/glatard/gists{/gist_id}","starred_url":"https://api.github.com/users/glatard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/glatard/subscriptions","organizations_url":"https://api.github.com/users/glatard/orgs","repos_url":"https://api.github.com/users/glatard/repos","events_url":"https://api.github.com/users/glatard/events{/privacy}","received_events_url":"https://api.github.com/users/glatard/received_events","type":"User","site_admin":false},"body":"OK!","created_at":"2016-07-14T11:46:49Z","updated_at":"2016-07-14T11:46:49Z","html_url":"https://github.com/boutiques/tools/pull/20#discussion_r70791469","pull_request_url":"https://api.github.com/repos/boutiques/tools/pulls/20","_links":{"self":{"href":"https://api.github.com/repos/boutiques/tools/pulls/comments/70791469"},"html":{"href":"https://github.com/boutiques/tools/pull/20#discussion_r70791469"},"pull_request":{"href":"https://api.github.com/repos/boutiques/tools/pulls/20"}}},"pull_request":{"url":"https://api.github.com/repos/boutiques/tools/pulls/20","id":77020676,"html_url":"https://github.com/boutiques/tools/pull/20","diff_url":"https://github.com/boutiques/tools/pull/20.diff","patch_url":"https://github.com/boutiques/tools/pull/20.patch","issue_url":"https://api.github.com/repos/boutiques/tools/issues/20","number":20,"state":"open","locked":false,"title":"Updating validator and adding a tool executor","user":{"login":"ttaa9","id":6237441,"avatar_url":"https://avatars.githubusercontent.com/u/6237441?v=3","gravatar_id":"","url":"https://api.github.com/users/ttaa9","html_url":"https://github.com/ttaa9","followers_url":"https://api.github.com/users/ttaa9/followers","following_url":"https://api.github.com/users/ttaa9/following{/other_user}","gists_url":"https://api.github.com/users/ttaa9/gists{/gist_id}","starred_url":"https://api.github.com/users/ttaa9/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ttaa9/subscriptions","organizations_url":"https://api.github.com/users/ttaa9/orgs","repos_url":"https://api.github.com/users/ttaa9/repos","events_url":"https://api.github.com/users/ttaa9/events{/privacy}","received_events_url":"https://api.github.com/users/ttaa9/received_events","type":"User","site_admin":false},"body":"To start addressing #19 and #17.\r\n\r\n- The validator now checks for some consistency with the schema (including the updates in boutiques/schema#40)\r\n- The local tool executor can take inputs in csv or json (or as a command-line string), check them for correctness against the descriptor, and then either print or execute the generated command line. It can also generate a random set of consistent input parameters and print the resulting command line (so the dev can check if a given random permitted input makes sense).","created_at":"2016-07-11T20:49:08Z","updated_at":"2016-07-14T11:46:49Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2863e0811c44ce5c63e09c08ff402cd0d2057387","assignee":{"login":"glatard","id":5174953,"avatar_url":"https://avatars.githubusercontent.com/u/5174953?v=3","gravatar_id":"","url":"https://api.github.com/users/glatard","html_url":"https://github.com/glatard","followers_url":"https://api.github.com/users/glatard/followers","following_url":"https://api.github.com/users/glatard/following{/other_user}","gists_url":"https://api.github.com/users/glatard/gists{/gist_id}","starred_url":"https://api.github.com/users/glatard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/glatard/subscriptions","organizations_url":"https://api.github.com/users/glatard/orgs","repos_url":"https://api.github.com/users/glatard/repos","events_url":"https://api.github.com/users/glatard/events{/privacy}","received_events_url":"https://api.github.com/users/glatard/received_events","type":"User","site_admin":false},"assignees":[{"login":"glatard","id":5174953,"avatar_url":"https://avatars.githubusercontent.com/u/5174953?v=3","gravatar_id":"","url":"https://api.github.com/users/glatard","html_url":"https://github.com/glatard","followers_url":"https://api.github.com/users/glatard/followers","following_url":"https://api.github.com/users/glatard/following{/other_user}","gists_url":"https://api.github.com/users/glatard/gists{/gist_id}","starred_url":"https://api.github.com/users/glatard/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/glatard/subscriptions","organizations_url":"https://api.github.com/users/glatard/orgs","repos_url":"https://api.github.com/users/glatard/repos","events_url":"https://api.github.com/users/glatard/events{/privacy}","received_events_url":"https://api.github.com/users/glatard/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/boutiques/tools/pulls/20/commits","review_comments_url":"https://api.github.com/repos/boutiques/tools/pulls/20/comments","review_comment_url":"https://api.github.com/repos/boutiques/tools/pulls/comments{/number}","comments_url":"https://api.github.com/repos/boutiques/tools/issues/20/comments","statuses_url":"https://api.github.com/repos/boutiques/tools/statuses/dc15bb8291f372abce8e434b29f095ae8b534269","head":{"label":"ttaa9:master","ref":"master","sha":"dc15bb8291f372abce8e434b29f095ae8b534269","user":{"login":"ttaa9","id":6237441,"avatar_url":"https://avatars.githubusercontent.com/u/6237441?v=3","gravatar_id":"","url":"https://api.github.com/users/ttaa9","html_url":"https://github.com/ttaa9","followers_url":"https://api.github.com/users/ttaa9/followers","following_url":"https://api.github.com/users/ttaa9/following{/other_user}","gists_url":"https://api.github.com/users/ttaa9/gists{/gist_id}","starred_url":"https://api.github.com/users/ttaa9/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ttaa9/subscriptions","organizations_url":"https://api.github.com/users/ttaa9/orgs","repos_url":"https://api.github.com/users/ttaa9/repos","events_url":"https://api.github.com/users/ttaa9/events{/privacy}","received_events_url":"https://api.github.com/users/ttaa9/received_events","type":"User","site_admin":false},"repo":{"id":62668844,"name":"tools","full_name":"ttaa9/tools","owner":{"login":"ttaa9","id":6237441,"avatar_url":"https://avatars.githubusercontent.com/u/6237441?v=3","gravatar_id":"","url":"https://api.github.com/users/ttaa9","html_url":"https://github.com/ttaa9","followers_url":"https://api.github.com/users/ttaa9/followers","following_url":"https://api.github.com/users/ttaa9/following{/other_user}","gists_url":"https://api.github.com/users/ttaa9/gists{/gist_id}","starred_url":"https://api.github.com/users/ttaa9/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ttaa9/subscriptions","organizations_url":"https://api.github.com/users/ttaa9/orgs","repos_url":"https://api.github.com/users/ttaa9/repos","events_url":"https://api.github.com/users/ttaa9/events{/privacy}","received_events_url":"https://api.github.com/users/ttaa9/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/ttaa9/tools","description":"Tools to create and use boutiques descriptors.","fork":true,"url":"https://api.github.com/repos/ttaa9/tools","forks_url":"https://api.github.com/repos/ttaa9/tools/forks","keys_url":"https://api.github.com/repos/ttaa9/tools/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ttaa9/tools/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ttaa9/tools/teams","hooks_url":"https://api.github.com/repos/ttaa9/tools/hooks","issue_events_url":"https://api.github.com/repos/ttaa9/tools/issues/events{/number}","events_url":"https://api.github.com/repos/ttaa9/tools/events","assignees_url":"https://api.github.com/repos/ttaa9/tools/assignees{/user}","branches_url":"https://api.github.com/repos/ttaa9/tools/branches{/branch}","tags_url":"https://api.github.com/repos/ttaa9/tools/tags","blobs_url":"https://api.github.com/repos/ttaa9/tools/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ttaa9/tools/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ttaa9/tools/git/refs{/sha}","trees_url":"https://api.github.com/repos/ttaa9/tools/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ttaa9/tools/statuses/{sha}","languages_url":"https://api.github.com/repos/ttaa9/tools/languages","stargazers_url":"https://api.github.com/repos/ttaa9/tools/stargazers","contributors_url":"https://api.github.com/repos/ttaa9/tools/contributors","subscribers_url":"https://api.github.com/repos/ttaa9/tools/subscribers","subscription_url":"https://api.github.com/repos/ttaa9/tools/subscription","commits_url":"https://api.github.com/repos/ttaa9/tools/commits{/sha}","git_commits_url":"https://api.github.com/repos/ttaa9/tools/git/commits{/sha}","comments_url":"https://api.github.com/repos/ttaa9/tools/comments{/number}","issue_comment_url":"https://api.github.com/repos/ttaa9/tools/issues/comments{/number}","contents_url":"https://api.github.com/repos/ttaa9/tools/contents/{+path}","compare_url":"https://api.github.com/repos/ttaa9/tools/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ttaa9/tools/merges","archive_url":"https://api.github.com/repos/ttaa9/tools/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ttaa9/tools/downloads","issues_url":"https://api.github.com/repos/ttaa9/tools/issues{/number}","pulls_url":"https://api.github.com/repos/ttaa9/tools/pulls{/number}","milestones_url":"https://api.github.com/repos/ttaa9/tools/milestones{/number}","notifications_url":"https://api.github.com/repos/ttaa9/tools/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ttaa9/tools/labels{/name}","releases_url":"https://api.github.com/repos/ttaa9/tools/releases{/id}","deployments_url":"https://api.github.com/repos/ttaa9/tools/deployments","created_at":"2016-07-05T20:51:09Z","updated_at":"2016-07-05T20:51:10Z","pushed_at":"2016-07-12T18:21:47Z","git_url":"git://github.com/ttaa9/tools.git","ssh_url":"git@github.com:ttaa9/tools.git","clone_url":"https://github.com/ttaa9/tools.git","svn_url":"https://github.com/ttaa9/tools","homepage":"","size":180,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"boutiques:master","ref":"master","sha":"0f9577867d74bbb03df07499734eb592fef5cf24","user":{"login":"boutiques","id":11424909,"avatar_url":"https://avatars.githubusercontent.com/u/11424909?v=3","gravatar_id":"","url":"https://api.github.com/users/boutiques","html_url":"https://github.com/boutiques","followers_url":"https://api.github.com/users/boutiques/followers","following_url":"https://api.github.com/users/boutiques/following{/other_user}","gists_url":"https://api.github.com/users/boutiques/gists{/gist_id}","starred_url":"https://api.github.com/users/boutiques/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/boutiques/subscriptions","organizations_url":"https://api.github.com/users/boutiques/orgs","repos_url":"https://api.github.com/users/boutiques/repos","events_url":"https://api.github.com/users/boutiques/events{/privacy}","received_events_url":"https://api.github.com/users/boutiques/received_events","type":"Organization","site_admin":false},"repo":{"id":32616174,"name":"tools","full_name":"boutiques/tools","owner":{"login":"boutiques","id":11424909,"avatar_url":"https://avatars.githubusercontent.com/u/11424909?v=3","gravatar_id":"","url":"https://api.github.com/users/boutiques","html_url":"https://github.com/boutiques","followers_url":"https://api.github.com/users/boutiques/followers","following_url":"https://api.github.com/users/boutiques/following{/other_user}","gists_url":"https://api.github.com/users/boutiques/gists{/gist_id}","starred_url":"https://api.github.com/users/boutiques/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/boutiques/subscriptions","organizations_url":"https://api.github.com/users/boutiques/orgs","repos_url":"https://api.github.com/users/boutiques/repos","events_url":"https://api.github.com/users/boutiques/events{/privacy}","received_events_url":"https://api.github.com/users/boutiques/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/boutiques/tools","description":"Tools to create and use boutiques descriptors.","fork":false,"url":"https://api.github.com/repos/boutiques/tools","forks_url":"https://api.github.com/repos/boutiques/tools/forks","keys_url":"https://api.github.com/repos/boutiques/tools/keys{/key_id}","collaborators_url":"https://api.github.com/repos/boutiques/tools/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/boutiques/tools/teams","hooks_url":"https://api.github.com/repos/boutiques/tools/hooks","issue_events_url":"https://api.github.com/repos/boutiques/tools/issues/events{/number}","events_url":"https://api.github.com/repos/boutiques/tools/events","assignees_url":"https://api.github.com/repos/boutiques/tools/assignees{/user}","branches_url":"https://api.github.com/repos/boutiques/tools/branches{/branch}","tags_url":"https://api.github.com/repos/boutiques/tools/tags","blobs_url":"https://api.github.com/repos/boutiques/tools/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/boutiques/tools/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/boutiques/tools/git/refs{/sha}","trees_url":"https://api.github.com/repos/boutiques/tools/git/trees{/sha}","statuses_url":"https://api.github.com/repos/boutiques/tools/statuses/{sha}","languages_url":"https://api.github.com/repos/boutiques/tools/languages","stargazers_url":"https://api.github.com/repos/boutiques/tools/stargazers","contributors_url":"https://api.github.com/repos/boutiques/tools/contributors","subscribers_url":"https://api.github.com/repos/boutiques/tools/subscribers","subscription_url":"https://api.github.com/repos/boutiques/tools/subscription","commits_url":"https://api.github.com/repos/boutiques/tools/commits{/sha}","git_commits_url":"https://api.github.com/repos/boutiques/tools/git/commits{/sha}","comments_url":"https://api.github.com/repos/boutiques/tools/comments{/number}","issue_comment_url":"https://api.github.com/repos/boutiques/tools/issues/comments{/number}","contents_url":"https://api.github.com/repos/boutiques/tools/contents/{+path}","compare_url":"https://api.github.com/repos/boutiques/tools/compare/{base}...{head}","merges_url":"https://api.github.com/repos/boutiques/tools/merges","archive_url":"https://api.github.com/repos/boutiques/tools/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/boutiques/tools/downloads","issues_url":"https://api.github.com/repos/boutiques/tools/issues{/number}","pulls_url":"https://api.github.com/repos/boutiques/tools/pulls{/number}","milestones_url":"https://api.github.com/repos/boutiques/tools/milestones{/number}","notifications_url":"https://api.github.com/repos/boutiques/tools/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/boutiques/tools/labels{/name}","releases_url":"https://api.github.com/repos/boutiques/tools/releases{/id}","deployments_url":"https://api.github.com/repos/boutiques/tools/deployments","created_at":"2015-03-21T01:59:35Z","updated_at":"2016-05-31T15:23:29Z","pushed_at":"2016-07-12T18:21:47Z","git_url":"git://github.com/boutiques/tools.git","ssh_url":"git@github.com:boutiques/tools.git","clone_url":"https://github.com/boutiques/tools.git","svn_url":"https://github.com/boutiques/tools","homepage":"","size":317,"stargazers_count":2,"watchers_count":2,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2,"mirror_url":null,"open_issues_count":7,"forks":2,"open_issues":7,"watchers":2,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/boutiques/tools/pulls/20"},"html":{"href":"https://github.com/boutiques/tools/pull/20"},"issue":{"href":"https://api.github.com/repos/boutiques/tools/issues/20"},"comments":{"href":"https://api.github.com/repos/boutiques/tools/issues/20/comments"},"review_comments":{"href":"https://api.github.com/repos/boutiques/tools/pulls/20/comments"},"review_comment":{"href":"https://api.github.com/repos/boutiques/tools/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/boutiques/tools/pulls/20/commits"},"statuses":{"href":"https://api.github.com/repos/boutiques/tools/statuses/dc15bb8291f372abce8e434b29f095ae8b534269"}}}}
{"actor":{"display_login":"glatard"}}