{"action":"created","comment":{"url":"https://api.github.com/repos/biocore/qiita/pulls/comments/53812701","id":53812701,"diff_hunk":"@@ -337,3 +507,466 @@ def step(self, value):\n                      WHERE processing_job_id = %s\"\"\"\n             qdb.sql_connection.TRN.add(sql, [value, self.id])\n             qdb.sql_connection.TRN.execute()\n+\n+    @property\n+    def children(self):\n+        \"\"\"The children jobs\n+\n+        Returns\n+        -------\n+        generator of qiita_db.processing_job.ProcessingJob\n+            The children jobs\n+        \"\"\"\n+        with qdb.sql_connection.TRN:\n+            sql = \"\"\"SELECT child_id\n+                     FROM qiita.parent_processing_job\n+                     WHERE parent_id = %s\"\"\"\n+            qdb.sql_connection.TRN.add(sql, [self.id])\n+            for jid in qdb.sql_connection.TRN.execute_fetchflatten():\n+                yield ProcessingJob(jid)\n+\n+    def _update_children(self, mapping):\n+        \"\"\"Updates the children of the current job to populate the input params\n+\n+        Parameters\n+        ----------\n+        mapping : dict of {int: int}\n+            The mapping between output parameter and artifact\n+\n+        Returns\n+        -------\n+        list of qiita_db.processing_job.ProcessingJob\n+            The list of childrens that are ready to be submitted\n+        \"\"\"\n+        ready = []\n+        with qdb.sql_connection.TRN:\n+            sql = \"\"\"SELECT command_output_id, name\n+                     FROM qiita.command_output\n+                     WHERE command_output_id IN %s\"\"\"\n+            sql_args = [tuple(mapping.keys())]\n+            qdb.sql_connection.TRN.add(sql, sql_args)\n+            res = qdb.sql_connection.TRN.execute_fetchindex()\n+            new_map = {name: mapping[oid] for oid, name in res}\n+\n+            sql = \"\"\"SELECT command_parameters, pending\n+                     FROM qiita.processing_job\n+                     WHERE processing_job_id = %s\"\"\"\n+            sql_update = \"\"\"UPDATE qiita.processing_job\n+                            SET command_parameters = %s,\n+                                pending = %s\n+                            WHERE processing_job_id = %s\"\"\"\n+            for c in self.children:\n+                qdb.sql_connection.TRN.add(sql, [c.id])\n+                params, pending = qdb.sql_connection.TRN.execute_fetchflatten()\n+                for pname, out_name in viewitems(pending[self.id]):\n+                    params[pname] = new_map[out_name]\n+                    del pending[self.id]\n+\n+                # Force to insert a NULL in the DB if pending is empty\n+                pending = pending if pending else None\n+                qdb.sql_connection.TRN.add(sql_update,\n+                                           [dumps(params), pending, c.id])\n+                qdb.sql_connection.TRN.execute()\n+\n+                if pending is None:\n+                    # The child already has all the parameters\n+                    # Add it to the ready list\n+                    ready.append(c)\n+        return ready\n+\n+    def _update_and_launch_children(self, mapping):\n+        \"\"\"Updates the children of the current job to populate the input params\n+\n+        Parameters\n+        ----------\n+        mapping : dict of {int: int}\n+            The mapping between output parameter and artifact\n+        \"\"\"\n+        ready = self._update_children(mapping)\n+        # Submit all the children that already have all the input parameters\n+        for c in ready:\n+            c.submit()\n+\n+\n+class ProcessingWorkflow(qdb.base.QiitaObject):\n+    \"\"\"Models a workflow defined by the user\n+\n+    Parameters\n+    ----------\n+    user : qiita_db.user.User\n+        The user that modeled the workflow\n+    root : list of qiita_db.processing_job.ProcessingJob\n+        The first job in the workflow\n+    \"\"\"\n+    _table = \"processing_job_workflow\"\n+\n+    @classmethod\n+    def _common_creation_steps(cls, user, root_jobs, name=None):\n+        \"\"\"Executes the common creation steps\n+\n+        Parameters\n+        ----------\n+        user : qiita_db.user.User\n+            The user creating the workflow\n+        root_jobs : list of qiita_db.processing_job.ProcessingJob\n+            The root jobs of the workflow\n+        name : str, optional\n+            The name of the workflow. Default: generated from user's name\n+        \"\"\"\n+        with qdb.sql_connection.TRN:\n+            # Insert the workflow in the processing_job_worflow table\n+            name = name if name else \"%s's workflow\" % user.info['name']\n+            sql = \"\"\"INSERT INTO qiita.processing_job_workflow (email, name)\n+                     VALUES (%s, %s)\n+                     RETURNING processing_job_workflow_id\"\"\"\n+            qdb.sql_connection.TRN.add(sql, [user.email, name])\n+            w_id = qdb.sql_connection.TRN.execute_fetchlast()\n+            # Connect the workflow with it's initial set of jobs\n+            sql = \"\"\"INSERT INTO qiita.processing_job_workflow_root\n+                        (processing_job_workflow_id, processing_job_id)\n+                     VALUES (%s, %s)\"\"\"\n+            sql_args = [[w_id, j.id] for j in root_jobs]\n+            qdb.sql_connection.TRN.add(sql, sql_args, many=True)\n+            qdb.sql_connection.TRN.execute()\n+\n+        return cls(w_id)\n+\n+    @classmethod\n+    def from_default_workflow(cls, user, dflt_wf, req_params, name=None):\n+        \"\"\"Creates a new processing workflow from a default workflow\n+\n+        Parameters\n+        ----------\n+        user : qiita_db.user.User\n+            The user creating the workflow\n+        dflt_wf : qiita_db.software.DefaultWorkflow\n+            The default workflow\n+        req_params : dict of {qdb.software.Command: dict of {str: object}}\n+            The required parameters values for the source commands in the\n+            workflow, keyed by command. The inner dicts are keyed by\n+            parameter name.\n+        name : str, optional\n+            Name of the workflow. Default: generated from user's name\n+\n+        Returns\n+        -------\n+        qiita_db.processing_job.ProcessingWorkflow\n+            The newly created workflow\n+        \"\"\"\n+        with qdb.sql_connection.TRN:\n+            dflt_g = dflt_wf.graph\n+\n+            # Find the roots of the workflow. That is, the nodes that do not\n+            # have a parent in the graph (in_degree = 0)\n+            in_degrees = dflt_g.in_degree()\n+\n+            # We can potentially access this information from the nodes\n+            # multiple times, so caching in here\n+            all_nodes = {n: (n.command, n.parameters)\n+                         for n in in_degrees}\n+            roots = {n: (n.command, n.parameters)\n+                     for n, d in viewitems(in_degrees) if d == 0}\n+\n+            # Check that we have all the required parameters\n+            root_cmds = set(c for c, _ in viewvalues(roots))\n+            if root_cmds != set(req_params):\n+                error_msg = ['Provided required parameters do not match the '\n+                             'initial set of commands for the workflow.']\n+                missing = [c.name for c in root_cmds - set(req_params)]\n+                if missing:\n+                    error_msg.append(\n+                        ' Command(s) \"%s\" are missing the required parameter '\n+                        'set.' % ', '.join(missing))\n+                extra = [c.name for c in set(req_params) - root_cmds]\n+                if extra:\n+                    error_msg.append(\n+                        ' Paramters for command(s) \"%s\" have been provided, '\n+                        'but they are not the initial commands for the '\n+                        'workflow.' % ', '.join(extra))\n+                raise qdb.exceptions.QiitaDBError(''.join(error_msg))\n+\n+            # Start creating the root jobs\n+            node_to_job = {\n+                n: ProcessingJob.create(\n+                    user,\n+                    qdb.software.Parameters.from_default_params(\n+                        p, req_params[c]))\n+                for n, (c, p) in viewitems(roots)}\n+            root_jobs = node_to_job.values()\n+\n+            # SQL used to create the edges between jobs\n+            sql = \"\"\"INSERT INTO qiita.parent_processing_job\n+                        (parent_id, child_id)\n+                     VALUES (%s, %s)\"\"\"\n+\n+            # Create the rest of the jobs. These are different form the root\n+            # jobs because they depend on other jobs to complete in order to be\n+            # submitted\n+            for n in nx.topological_sort(dflt_g):\n+                if n in node_to_job:\n+                    # We have already seend this node\n+                    # (because it is a root node)\n+                    continue\n+\n+                cmd, dflt_params = all_nodes[n]\n+                job_req_params = {}\n+                parent_ids = []\n+\n+                # Each incoming edge represents an artifact that is generated\n+                # by the source job of the edge\n+                for source, dest, data in dflt_g.in_edges(n, data=True):\n+                    # Retrieve the id of the parent job - it already exists\n+                    # because we are visiting the nodes in topological order\n+                    source_id = node_to_job[source].id\n+                    parent_ids.append(source_id)\n+                    # Get the connections between the job and the source\n+                    connections = data['connections'].connections\n+                    for out, in_param in connections:\n+                        # We take advantage of the fact the parameters are\n+                        # stored in JSON to encode the name of the output\n+                        # artifact from\n+                        # the previous job","path":"qiita_db/processing_job.py","position":527,"original_position":527,"commit_id":"d78be983177cceaaac01990e6b229cccb3f51fcc","original_commit_id":"d78be983177cceaaac01990e6b229cccb3f51fcc","user":{"login":"josenavas","id":2501478,"avatar_url":"https://avatars.githubusercontent.com/u/2501478?v=3","gravatar_id":"","url":"https://api.github.com/users/josenavas","html_url":"https://github.com/josenavas","followers_url":"https://api.github.com/users/josenavas/followers","following_url":"https://api.github.com/users/josenavas/following{/other_user}","gists_url":"https://api.github.com/users/josenavas/gists{/gist_id}","starred_url":"https://api.github.com/users/josenavas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/josenavas/subscriptions","organizations_url":"https://api.github.com/users/josenavas/orgs","repos_url":"https://api.github.com/users/josenavas/repos","events_url":"https://api.github.com/users/josenavas/events{/privacy}","received_events_url":"https://api.github.com/users/josenavas/received_events","type":"User","site_admin":false},"body":"Done","created_at":"2016-02-23T17:05:30Z","updated_at":"2016-02-23T17:05:30Z","html_url":"https://github.com/biocore/qiita/pull/1641#discussion_r53812701","pull_request_url":"https://api.github.com/repos/biocore/qiita/pulls/1641","_links":{"self":{"href":"https://api.github.com/repos/biocore/qiita/pulls/comments/53812701"},"html":{"href":"https://github.com/biocore/qiita/pull/1641#discussion_r53812701"},"pull_request":{"href":"https://api.github.com/repos/biocore/qiita/pulls/1641"}}},"pull_request":{"url":"https://api.github.com/repos/biocore/qiita/pulls/1641","id":58999242,"html_url":"https://github.com/biocore/qiita/pull/1641","diff_url":"https://github.com/biocore/qiita/pull/1641.diff","patch_url":"https://github.com/biocore/qiita/pull/1641.patch","issue_url":"https://api.github.com/repos/biocore/qiita/issues/1641","number":1641,"state":"open","locked":false,"title":"Workflow object","user":{"login":"josenavas","id":2501478,"avatar_url":"https://avatars.githubusercontent.com/u/2501478?v=3","gravatar_id":"","url":"https://api.github.com/users/josenavas","html_url":"https://github.com/josenavas","followers_url":"https://api.github.com/users/josenavas/followers","following_url":"https://api.github.com/users/josenavas/following{/other_user}","gists_url":"https://api.github.com/users/josenavas/gists{/gist_id}","starred_url":"https://api.github.com/users/josenavas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/josenavas/subscriptions","organizations_url":"https://api.github.com/users/josenavas/orgs","repos_url":"https://api.github.com/users/josenavas/repos","events_url":"https://api.github.com/users/josenavas/events{/privacy}","received_events_url":"https://api.github.com/users/josenavas/received_events","type":"User","site_admin":false},"body":"This PR adds the necessary DB structure to support default workflows from plugins and user-generated workflows.\r\n\r\nOverview of changes in this PR:\r\n- Structures added to the DB to support default workflows from plugins.\r\n- DefaultWorkflow object (and aux classes) added to access the default workflows.\r\n- Small table added to keep track of the user-generated workflow\r\n- _Currently not implemented (will be in tomorrow):_ ProcessingWorkflow object to access the user defined workflows.\r\n- In order to implement the above class, we need to keep track of which artifacts have been generated from which ProcessingJob. This adds another table to the database and adds some work on job completion. This triggered changes in the ProcessingJob object, so more work is kept internally to the object rather than outside of the object, forcing to make changes in the restAPI handlers, restAPI interface and plugins (to meet the new requirements of the restAPI).","created_at":"2016-02-11T07:40:38Z","updated_at":"2016-02-23T17:05:30Z","closed_at":null,"merged_at":null,"merge_commit_sha":"ffc40b11beb961c562666b30af7fcc38148669bd","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/biocore/qiita/pulls/1641/commits","review_comments_url":"https://api.github.com/repos/biocore/qiita/pulls/1641/comments","review_comment_url":"https://api.github.com/repos/biocore/qiita/pulls/comments{/number}","comments_url":"https://api.github.com/repos/biocore/qiita/issues/1641/comments","statuses_url":"https://api.github.com/repos/biocore/qiita/statuses/d78be983177cceaaac01990e6b229cccb3f51fcc","head":{"label":"josenavas:workflow-object","ref":"workflow-object","sha":"d78be983177cceaaac01990e6b229cccb3f51fcc","user":{"login":"josenavas","id":2501478,"avatar_url":"https://avatars.githubusercontent.com/u/2501478?v=3","gravatar_id":"","url":"https://api.github.com/users/josenavas","html_url":"https://github.com/josenavas","followers_url":"https://api.github.com/users/josenavas/followers","following_url":"https://api.github.com/users/josenavas/following{/other_user}","gists_url":"https://api.github.com/users/josenavas/gists{/gist_id}","starred_url":"https://api.github.com/users/josenavas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/josenavas/subscriptions","organizations_url":"https://api.github.com/users/josenavas/orgs","repos_url":"https://api.github.com/users/josenavas/repos","events_url":"https://api.github.com/users/josenavas/events{/privacy}","received_events_url":"https://api.github.com/users/josenavas/received_events","type":"User","site_admin":false},"repo":{"id":13527677,"name":"QiiTa","full_name":"josenavas/QiiTa","owner":{"login":"josenavas","id":2501478,"avatar_url":"https://avatars.githubusercontent.com/u/2501478?v=3","gravatar_id":"","url":"https://api.github.com/users/josenavas","html_url":"https://github.com/josenavas","followers_url":"https://api.github.com/users/josenavas/followers","following_url":"https://api.github.com/users/josenavas/following{/other_user}","gists_url":"https://api.github.com/users/josenavas/gists{/gist_id}","starred_url":"https://api.github.com/users/josenavas/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/josenavas/subscriptions","organizations_url":"https://api.github.com/users/josenavas/orgs","repos_url":"https://api.github.com/users/josenavas/repos","events_url":"https://api.github.com/users/josenavas/events{/privacy}","received_events_url":"https://api.github.com/users/josenavas/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/josenavas/QiiTa","description":"QiiTa databasing effort","fork":true,"url":"https://api.github.com/repos/josenavas/QiiTa","forks_url":"https://api.github.com/repos/josenavas/QiiTa/forks","keys_url":"https://api.github.com/repos/josenavas/QiiTa/keys{/key_id}","collaborators_url":"https://api.github.com/repos/josenavas/QiiTa/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/josenavas/QiiTa/teams","hooks_url":"https://api.github.com/repos/josenavas/QiiTa/hooks","issue_events_url":"https://api.github.com/repos/josenavas/QiiTa/issues/events{/number}","events_url":"https://api.github.com/repos/josenavas/QiiTa/events","assignees_url":"https://api.github.com/repos/josenavas/QiiTa/assignees{/user}","branches_url":"https://api.github.com/repos/josenavas/QiiTa/branches{/branch}","tags_url":"https://api.github.com/repos/josenavas/QiiTa/tags","blobs_url":"https://api.github.com/repos/josenavas/QiiTa/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/josenavas/QiiTa/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/josenavas/QiiTa/git/refs{/sha}","trees_url":"https://api.github.com/repos/josenavas/QiiTa/git/trees{/sha}","statuses_url":"https://api.github.com/repos/josenavas/QiiTa/statuses/{sha}","languages_url":"https://api.github.com/repos/josenavas/QiiTa/languages","stargazers_url":"https://api.github.com/repos/josenavas/QiiTa/stargazers","contributors_url":"https://api.github.com/repos/josenavas/QiiTa/contributors","subscribers_url":"https://api.github.com/repos/josenavas/QiiTa/subscribers","subscription_url":"https://api.github.com/repos/josenavas/QiiTa/subscription","commits_url":"https://api.github.com/repos/josenavas/QiiTa/commits{/sha}","git_commits_url":"https://api.github.com/repos/josenavas/QiiTa/git/commits{/sha}","comments_url":"https://api.github.com/repos/josenavas/QiiTa/comments{/number}","issue_comment_url":"https://api.github.com/repos/josenavas/QiiTa/issues/comments{/number}","contents_url":"https://api.github.com/repos/josenavas/QiiTa/contents/{+path}","compare_url":"https://api.github.com/repos/josenavas/QiiTa/compare/{base}...{head}","merges_url":"https://api.github.com/repos/josenavas/QiiTa/merges","archive_url":"https://api.github.com/repos/josenavas/QiiTa/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/josenavas/QiiTa/downloads","issues_url":"https://api.github.com/repos/josenavas/QiiTa/issues{/number}","pulls_url":"https://api.github.com/repos/josenavas/QiiTa/pulls{/number}","milestones_url":"https://api.github.com/repos/josenavas/QiiTa/milestones{/number}","notifications_url":"https://api.github.com/repos/josenavas/QiiTa/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/josenavas/QiiTa/labels{/name}","releases_url":"https://api.github.com/repos/josenavas/QiiTa/releases{/id}","deployments_url":"https://api.github.com/repos/josenavas/QiiTa/deployments","created_at":"2013-10-12T19:29:32Z","updated_at":"2015-05-05T22:50:05Z","pushed_at":"2016-02-23T16:49:43Z","git_url":"git://github.com/josenavas/QiiTa.git","ssh_url":"git@github.com:josenavas/QiiTa.git","clone_url":"https://github.com/josenavas/QiiTa.git","svn_url":"https://github.com/josenavas/QiiTa","homepage":null,"size":129158,"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":"biocore:artifact-study-pages","ref":"artifact-study-pages","sha":"a96603365f84d1f59935b2178150ec0037f1143c","user":{"login":"biocore","id":6241857,"avatar_url":"https://avatars.githubusercontent.com/u/6241857?v=3","gravatar_id":"","url":"https://api.github.com/users/biocore","html_url":"https://github.com/biocore","followers_url":"https://api.github.com/users/biocore/followers","following_url":"https://api.github.com/users/biocore/following{/other_user}","gists_url":"https://api.github.com/users/biocore/gists{/gist_id}","starred_url":"https://api.github.com/users/biocore/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/biocore/subscriptions","organizations_url":"https://api.github.com/users/biocore/orgs","repos_url":"https://api.github.com/users/biocore/repos","events_url":"https://api.github.com/users/biocore/events{/privacy}","received_events_url":"https://api.github.com/users/biocore/received_events","type":"Organization","site_admin":false},"repo":{"id":13131245,"name":"qiita","full_name":"biocore/qiita","owner":{"login":"biocore","id":6241857,"avatar_url":"https://avatars.githubusercontent.com/u/6241857?v=3","gravatar_id":"","url":"https://api.github.com/users/biocore","html_url":"https://github.com/biocore","followers_url":"https://api.github.com/users/biocore/followers","following_url":"https://api.github.com/users/biocore/following{/other_user}","gists_url":"https://api.github.com/users/biocore/gists{/gist_id}","starred_url":"https://api.github.com/users/biocore/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/biocore/subscriptions","organizations_url":"https://api.github.com/users/biocore/orgs","repos_url":"https://api.github.com/users/biocore/repos","events_url":"https://api.github.com/users/biocore/events{/privacy}","received_events_url":"https://api.github.com/users/biocore/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/biocore/qiita","description":"Qiita - A QIIME databasing effort","fork":false,"url":"https://api.github.com/repos/biocore/qiita","forks_url":"https://api.github.com/repos/biocore/qiita/forks","keys_url":"https://api.github.com/repos/biocore/qiita/keys{/key_id}","collaborators_url":"https://api.github.com/repos/biocore/qiita/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/biocore/qiita/teams","hooks_url":"https://api.github.com/repos/biocore/qiita/hooks","issue_events_url":"https://api.github.com/repos/biocore/qiita/issues/events{/number}","events_url":"https://api.github.com/repos/biocore/qiita/events","assignees_url":"https://api.github.com/repos/biocore/qiita/assignees{/user}","branches_url":"https://api.github.com/repos/biocore/qiita/branches{/branch}","tags_url":"https://api.github.com/repos/biocore/qiita/tags","blobs_url":"https://api.github.com/repos/biocore/qiita/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/biocore/qiita/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/biocore/qiita/git/refs{/sha}","trees_url":"https://api.github.com/repos/biocore/qiita/git/trees{/sha}","statuses_url":"https://api.github.com/repos/biocore/qiita/statuses/{sha}","languages_url":"https://api.github.com/repos/biocore/qiita/languages","stargazers_url":"https://api.github.com/repos/biocore/qiita/stargazers","contributors_url":"https://api.github.com/repos/biocore/qiita/contributors","subscribers_url":"https://api.github.com/repos/biocore/qiita/subscribers","subscription_url":"https://api.github.com/repos/biocore/qiita/subscription","commits_url":"https://api.github.com/repos/biocore/qiita/commits{/sha}","git_commits_url":"https://api.github.com/repos/biocore/qiita/git/commits{/sha}","comments_url":"https://api.github.com/repos/biocore/qiita/comments{/number}","issue_comment_url":"https://api.github.com/repos/biocore/qiita/issues/comments{/number}","contents_url":"https://api.github.com/repos/biocore/qiita/contents/{+path}","compare_url":"https://api.github.com/repos/biocore/qiita/compare/{base}...{head}","merges_url":"https://api.github.com/repos/biocore/qiita/merges","archive_url":"https://api.github.com/repos/biocore/qiita/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/biocore/qiita/downloads","issues_url":"https://api.github.com/repos/biocore/qiita/issues{/number}","pulls_url":"https://api.github.com/repos/biocore/qiita/pulls{/number}","milestones_url":"https://api.github.com/repos/biocore/qiita/milestones{/number}","notifications_url":"https://api.github.com/repos/biocore/qiita/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/biocore/qiita/labels{/name}","releases_url":"https://api.github.com/repos/biocore/qiita/releases{/id}","deployments_url":"https://api.github.com/repos/biocore/qiita/deployments","created_at":"2013-09-26T18:50:43Z","updated_at":"2016-01-31T22:47:34Z","pushed_at":"2016-02-23T16:49:45Z","git_url":"git://github.com/biocore/qiita.git","ssh_url":"git@github.com:biocore/qiita.git","clone_url":"https://github.com/biocore/qiita.git","svn_url":"https://github.com/biocore/qiita","homepage":"http://qiita.microbio.me","size":129877,"stargazers_count":25,"watchers_count":25,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":27,"mirror_url":null,"open_issues_count":323,"forks":27,"open_issues":323,"watchers":25,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/biocore/qiita/pulls/1641"},"html":{"href":"https://github.com/biocore/qiita/pull/1641"},"issue":{"href":"https://api.github.com/repos/biocore/qiita/issues/1641"},"comments":{"href":"https://api.github.com/repos/biocore/qiita/issues/1641/comments"},"review_comments":{"href":"https://api.github.com/repos/biocore/qiita/pulls/1641/comments"},"review_comment":{"href":"https://api.github.com/repos/biocore/qiita/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/biocore/qiita/pulls/1641/commits"},"statuses":{"href":"https://api.github.com/repos/biocore/qiita/statuses/d78be983177cceaaac01990e6b229cccb3f51fcc"}}}}