{"action":"created","comment":{"url":"https://api.github.com/repos/Ensembl/ensembl-compara/pulls/comments/347956518","pull_request_review_id":318990500,"id":347956518,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDM0Nzk1NjUxOA==","diff_hunk":"@@ -0,0 +1,245 @@\n+\n+from sqlalchemy import create_engine\n+from sqlalchemy.sql import text\n+from ensembl.compara.citest.test import Test\n+\n+\n+## This class extend the base class Test to test data into the database\n+## this test start with an intialisation\n+##\n+class TableTest(Test):\n+\n+    def __init__(self):\n+        Test.__init__(self)\n+        self.ref_connection_engine=None\n+        self.target_connection_engine=None\n+        self.table_tests=[]\n+\n+\n+    def initialise_tests(self,dic_argument): # str_pipeline_name, obj_ref_connection, obj_target_connection, lst_table_tests):\n+        self.pipeline_name=dic_argument[\"str_pipeline_name\"]\n+        self.ref_connection_engine=dic_argument[\"obj_ref_connection_engine\"]\n+        self.target_connection_engine=dic_argument[\"obj_target_connection_engine\"]\n+        self.table_tests=dic_argument[\"lst_table_tests\"]\n+\n+        ###Test that the all tables define in lst_table_tests exists in the databases\n+        lst_tables_database=self._get_pipeline_table(self.ref_connection_engine)\n+        for dic_tabl_test in self.table_tests:\n+            str_table_name=dic_tabl_test[\"name\"]\n+            if not str_table_name in lst_tables_database:\n+                raise Exception(\"Error: table name '\"+str_table_name+\"' is not in the database\")\n+\n+\n+    def _get_pipeline_table(self, obj_connection_engine):\n+            TABL_NAME=0\n+            lst_pipeline_table_names=[]\n+            str_request=\"SHOW TABLE STATUS WHERE Rows > 0;\"\n+            obj_request = text(str_request)\n+            obj_connection=obj_connection_engine.connect()\n+            obj_result=obj_connection.execute(obj_request)\n+            for row in obj_result:\n+                str_table_name=row[TABL_NAME]\n+                lst_pipeline_table_names.append(str_table_name)\n+            obj_connection.close()\n+            return lst_pipeline_table_names\n+\n+\n+    def run_tests(self):\n+        for dic_tabl_test in self.table_tests:\n+            str_table_name=dic_tabl_test[\"name\"]\n+            int_line_variation=dic_tabl_test[\"variation\"]\n+            lst_group_by=dic_tabl_test[\"lst_group_by\"]\n+            lst_columns=dic_tabl_test[\"columns\"]\n+\n+            #First it compare the number of row between the ref and target db\n+            self._test_table_number_row(str_table_name, int_line_variation)\n+\n+            #test the group if defined in json\n+            if not lst_group_by ==[]:\n+                self._test_table_number_row_by_group(str_table_name, lst_group_by)\n+\n+            #test field if present in json\n+            if not lst_columns ==[]:\n+                self._test_table_by_column(str_table_name,lst_columns)\n+\n+\n+    def _test_table_number_row(self, str_table_name, flt_variation):\n+        result={}\n+        #do the check for the given table\n+        int_nb_row_ref=self._get_number_row(self.ref_connection_engine, str_table_name)\n+        int_nb_row_tar=self._get_number_row(self.target_connection_engine, str_table_name)\n+        int_variation =int(int_nb_row_ref*flt_variation)\n+        if abs(int_nb_row_ref - int_nb_row_tar) <= int_variation: # if the test is succesful\n+            result[\"succes\"]=1\n+        else:\n+            result[\"succes\"]=0\n+        #populate results with\n+        str_info=\"ref:\"+str(int_nb_row_ref)+\"|\"+\"tar:\"+str(int_nb_row_tar)+\"|var:\"+str(int_nb_row_ref - int_nb_row_tar)\n+        str_info=str_info+\"|exp:\"+str(int_variation)\n+        result[\"info\"]=str_info\n+        result[\"table\"]=str_table_name\n+        result[\"type\"]=\"nb_row\"\n+        self.test_results.append(result)\n+\n+\n+    def _get_number_row(self,obj_connection_engine, str_table_name):\n+        str_request=\"select count(*) from \"+str_table_name+\";\"\n+        obj_request=text(str_request)\n+        obj_connection=obj_connection_engine.connect()\n+        obj_result=obj_connection.execute(obj_request)\n+        nbRow=0\n+        for tpl_row in obj_result:\n+            int_nb_row=tpl_row[0]\n+        obj_connection.close()\n+        return int_nb_row\n+\n+\n+    def _get_autorised_variation_by_group(self,lst_info_group, lst_variations):\n+            dic_variation={}\n+            for dic_var in lst_variations:\n+                dic_variation[dic_var[\"group\"]]=dic_var[\"var\"]\n+            dic_result={}\n+            for tpl_group in lst_info_group:\n+                dic_result[tpl_group[1]]=0\n+                if tpl_group[1] in dic_variation:\n+                    int_nb_var=int(tpl_group[0]*dic_variation[tpl_group[1]])\n+                    dic_result[tpl_group[1]]=int_nb_var\n+            return dic_result\n+\n+\n+    def _test_table_number_row_by_group(self, str_table_name, lst_groups):\n+\n+        for dic_group in lst_groups:\n+            str_group_by=dic_group[\"name\"]\n+            lst_variations=dic_group[\"variations\"]\n+\n+            #do the check for the given table\n+            lst_result_ref=self._get_number_row_by_group(self.ref_connection_engine, str_table_name, str_group_by)\n+            lst_result_tar=self._get_number_row_by_group(self.target_connection_engine, str_table_name, str_group_by)\n+\n+            ## test if the bunber of group are similar between the two datases\n+            ## if not then failure and stop here the group by check\n+            result={}\n+            result[\"succes\"]=0\n+            if len(lst_result_ref) == len(lst_result_tar):\n+                result[\"succes\"]=1\n+            str_info=\"grp:\"+str_group_by+\"|ref:\"+str(len(lst_result_ref))+\"|tar:\"+str(len(lst_result_tar))\n+            result[\"info\"]=str_info\n+            result[\"table\"]=str_table_name\n+            result[\"type\"]=\"nb_row_all_grp\"\n+            self.test_results.append(result)\n+            if result[\"succes\"]==0:#if the number of group is not the same then there is no reason to continue\n+                return\n+\n+            #load the number of autoiruied vairaiton (if group not describe in json then the variaiton expected is 0)\n+            dic_autorised_variation=self._get_autorised_variation_by_group(lst_result_ref, lst_variations)\n+\n+            ### for aech group check that the numbers do nat variate more than autorised.\n+            i=0\n+            while i < len(lst_result_ref):\n+                int_variation=dic_autorised_variation[lst_result_ref[i][1]]#get the aurrised variation for the group\n+                result={}\n+                result[\"succes\"]=0\n+                if abs(lst_result_ref[i][0]-lst_result_tar[i][0])<=int_variation: #if the number of each group is different\n+                    result[\"succes\"]=1\n+                str_info=\"grp:\"+str_group_by+\"|grp_ref:\"+str(lst_result_ref[i][1])+\"|nb_ref:\"+str(lst_result_ref[i][0])\n+                str_info=str_info+\"|grp_tar:\"+str(lst_result_tar[i][1])+\"|nb_tar:\"+str(lst_result_tar[i][0])+\"|var:\"+str(abs(lst_result_ref[i][0]-lst_result_tar[i][0]))\n+\n+                result[\"info\"]=str_info\n+                result[\"table\"]=str_table_name\n+                result[\"type\"]=\"nb_row_by_grp\"\n+                self.test_results.append(result)\n+                i=i+1\n+\n+\n+    def _get_number_row_by_group(self,obj_connection_engine,str_table_name,str_group_by):\n+        lst_result=[]\n+        str_request=\"select count(*),\"+str_group_by+\" from \"+str_table_name+\" group by \"+str_group_by+\";\"\n+        obj_request=text(str_request)\n+        obj_connection=obj_connection_engine.connect()\n+        obj_result=obj_connection.execute(obj_request)\n+        for tpl_res in obj_result:\n+            lst_result.append(tpl_res)\n+        obj_connection.close()\n+        return sorted(lst_result,key=lambda tuple: tuple[1])# return a list sorted on the group_by value\n+\n+\n+    def _test_table_by_column(self, str_table_name, lst_columns):\n+\n+        # transfornm the json based column in sinmple stroing list.\n+        lst_col =[]\n+        for column in lst_columns:\n+            lst_col.append(column[\"name\"])\n+\n+        dic_column_ref=self._get_column_values(self.ref_connection_engine, str_table_name, lst_col)\n+        dic_column_tar=self._get_column_values(self.target_connection_engine, str_table_name, lst_col)\n+\n+        for str_column, lst_fields_ref in dic_column_ref.items():\n+            lst_fields_tar=dic_column_tar[str_column]\n+            i=0\n+            result={}\n+            result[\"succes\"]=1\n+            str_val_ref=\"\"\n+            str_val_tar=\"\"\n+            while i < len(lst_fields_ref):\n+                if lst_fields_ref[i] != lst_fields_tar[i]:\n+                    result[\"succes\"]=0\n+                    str_val_ref=lst_fields_ref[i]\n+                    str_val_tar=lst_fields_tar[i]\n+                    break\n+                i=i+1\n+            str_info=\"col:\"+str_column+\"|val_ref:\"+str(str_val_ref)+\"|val_tar:\"+str(str_val_tar)\n+            result[\"info\"]=str_info\n+            result[\"table\"]=str_table_name\n+            result[\"type\"]=\"column\"\n+            self.test_results.append(result)\n+\n+\n+    def _get_column_values(self, obj_connection_engine, str_table, lst_columns):\n+        # init dictionary\n+        dic_column={}\n+        str_request=\"\"\n+        bool_tag_all=False\n+\n+        #look if there is a \"*\" in the list of fields\n+        for str_column in lst_columns:\n+            if str_column==\"*\":\n+                bool_tag_all=True\n+\n+        #if there is a star selct all, toherise select the selected tables\n+        if bool_tag_all:\n+            str_request=\"select * from \"+str_table+\";\"\n+        elif len(lst_columns)==1:\n+            str_request=\"select \"+lst_columns[0]+\" from \"+str_table+\";\"\n+        else:\n+            str_request=\"select \"+\",\".join(lst_columns)+\" from \"+str_table+\";\"\n+\n+        obj_request=text(str_request)\n+        obj_connection=obj_connection_engine.connect()\n+        obj_result=obj_connection.execute(obj_request)\n+\n+\n+        for str_col in obj_result.keys():\n+            # if there is a \"*\" in the lst column then all other columns are\n+            # defined to be excluded so we exclud them\n+            if bool_tag_all and str(str_col) in lst_columns:\n+                continue\n+            dic_column[str(str_col)]=[]\n+\n+        # convert the result by row into a result by column","path":"src/python/modules/ensembl/compara/citest/tabletest.py","position":229,"original_position":229,"commit_id":"67aa149696ac9a1185e9954590b3cd3c6aea9687","original_commit_id":"67aa149696ac9a1185e9954590b3cd3c6aea9687","user":{"login":"carlacummins","id":4394850,"node_id":"MDQ6VXNlcjQzOTQ4NTA=","avatar_url":"https://avatars3.githubusercontent.com/u/4394850?v=4","gravatar_id":"","url":"https://api.github.com/users/carlacummins","html_url":"https://github.com/carlacummins","followers_url":"https://api.github.com/users/carlacummins/followers","following_url":"https://api.github.com/users/carlacummins/following{/other_user}","gists_url":"https://api.github.com/users/carlacummins/gists{/gist_id}","starred_url":"https://api.github.com/users/carlacummins/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/carlacummins/subscriptions","organizations_url":"https://api.github.com/users/carlacummins/orgs","repos_url":"https://api.github.com/users/carlacummins/repos","events_url":"https://api.github.com/users/carlacummins/events{/privacy}","received_events_url":"https://api.github.com/users/carlacummins/received_events","type":"User","site_admin":false},"body":"AFAIK, this is akin to transposing a matrix, which `numpy` can do very well: https://docs.scipy.org/doc/numpy/reference/generated/numpy.transpose.html","created_at":"2019-11-19T14:32:11Z","updated_at":"2019-11-19T14:45:25Z","html_url":"https://github.com/Ensembl/ensembl-compara/pull/157#discussion_r347956518","pull_request_url":"https://api.github.com/repos/Ensembl/ensembl-compara/pulls/157","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/Ensembl/ensembl-compara/pulls/comments/347956518"},"html":{"href":"https://github.com/Ensembl/ensembl-compara/pull/157#discussion_r347956518"},"pull_request":{"href":"https://api.github.com/repos/Ensembl/ensembl-compara/pulls/157"}}},"pull_request":{"url":"https://api.github.com/repos/Ensembl/ensembl-compara/pulls/157","id":339924266,"node_id":"MDExOlB1bGxSZXF1ZXN0MzM5OTI0MjY2","html_url":"https://github.com/Ensembl/ensembl-compara/pull/157","diff_url":"https://github.com/Ensembl/ensembl-compara/pull/157.diff","patch_url":"https://github.com/Ensembl/ensembl-compara/pull/157.patch","issue_url":"https://api.github.com/repos/Ensembl/ensembl-compara/issues/157","number":157,"state":"open","locked":false,"title":"Dev/citest","user":{"login":"dthybert","id":57136240,"node_id":"MDQ6VXNlcjU3MTM2MjQw","avatar_url":"https://avatars0.githubusercontent.com/u/57136240?v=4","gravatar_id":"","url":"https://api.github.com/users/dthybert","html_url":"https://github.com/dthybert","followers_url":"https://api.github.com/users/dthybert/followers","following_url":"https://api.github.com/users/dthybert/following{/other_user}","gists_url":"https://api.github.com/users/dthybert/gists{/gist_id}","starred_url":"https://api.github.com/users/dthybert/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dthybert/subscriptions","organizations_url":"https://api.github.com/users/dthybert/orgs","repos_url":"https://api.github.com/users/dthybert/repos","events_url":"https://api.github.com/users/dthybert/events{/privacy}","received_events_url":"https://api.github.com/users/dthybert/received_events","type":"User","site_admin":false},"body":"This is the initial generic tool for CITest. The tool is able to make db comparison with tests specified in json file. The test has been developed using the LoadMember pipeline where strict comparison are done.Note that while comparison with margin error are authorised it has not been tested in the context of LoadMember.\r\nThe package includes:\r\n - LoadMember.json : describing the test to be done for LoadMemeber\r\n - LoadMembers_conf.pm : the configuration file for runiing the the pipeline under CITest environment\r\n - CITest.py : the main script to be executed for running the tests\r\n - citest.py: file describing the the main class citest which read config file and run test\r\n - test.py: file describing the base class for a test. This class has to be inherited and extended to impleemnt specific tests (dbtests, file test, tre etc...)\r\n -tabletest.py file describing the class that test database tables (inherit from Test)\r\n\r\n","created_at":"2019-11-12T14:01:19Z","updated_at":"2019-11-19T14:45:23Z","closed_at":null,"merged_at":null,"merge_commit_sha":"8693dabdb4e39c5f88ee30aa80af1a23d0e77e08","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/Ensembl/ensembl-compara/pulls/157/commits","review_comments_url":"https://api.github.com/repos/Ensembl/ensembl-compara/pulls/157/comments","review_comment_url":"https://api.github.com/repos/Ensembl/ensembl-compara/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Ensembl/ensembl-compara/issues/157/comments","statuses_url":"https://api.github.com/repos/Ensembl/ensembl-compara/statuses/67aa149696ac9a1185e9954590b3cd3c6aea9687","head":{"label":"dthybert:dev/citest","ref":"dev/citest","sha":"67aa149696ac9a1185e9954590b3cd3c6aea9687","user":{"login":"dthybert","id":57136240,"node_id":"MDQ6VXNlcjU3MTM2MjQw","avatar_url":"https://avatars0.githubusercontent.com/u/57136240?v=4","gravatar_id":"","url":"https://api.github.com/users/dthybert","html_url":"https://github.com/dthybert","followers_url":"https://api.github.com/users/dthybert/followers","following_url":"https://api.github.com/users/dthybert/following{/other_user}","gists_url":"https://api.github.com/users/dthybert/gists{/gist_id}","starred_url":"https://api.github.com/users/dthybert/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dthybert/subscriptions","organizations_url":"https://api.github.com/users/dthybert/orgs","repos_url":"https://api.github.com/users/dthybert/repos","events_url":"https://api.github.com/users/dthybert/events{/privacy}","received_events_url":"https://api.github.com/users/dthybert/received_events","type":"User","site_admin":false},"repo":{"id":221012821,"node_id":"MDEwOlJlcG9zaXRvcnkyMjEwMTI4MjE=","name":"ensembl-compara","full_name":"dthybert/ensembl-compara","private":false,"owner":{"login":"dthybert","id":57136240,"node_id":"MDQ6VXNlcjU3MTM2MjQw","avatar_url":"https://avatars0.githubusercontent.com/u/57136240?v=4","gravatar_id":"","url":"https://api.github.com/users/dthybert","html_url":"https://github.com/dthybert","followers_url":"https://api.github.com/users/dthybert/followers","following_url":"https://api.github.com/users/dthybert/following{/other_user}","gists_url":"https://api.github.com/users/dthybert/gists{/gist_id}","starred_url":"https://api.github.com/users/dthybert/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dthybert/subscriptions","organizations_url":"https://api.github.com/users/dthybert/orgs","repos_url":"https://api.github.com/users/dthybert/repos","events_url":"https://api.github.com/users/dthybert/events{/privacy}","received_events_url":"https://api.github.com/users/dthybert/received_events","type":"User","site_admin":false},"html_url":"https://github.com/dthybert/ensembl-compara","description":"The Ensembl Compara Perl API and SQL schema","fork":true,"url":"https://api.github.com/repos/dthybert/ensembl-compara","forks_url":"https://api.github.com/repos/dthybert/ensembl-compara/forks","keys_url":"https://api.github.com/repos/dthybert/ensembl-compara/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dthybert/ensembl-compara/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dthybert/ensembl-compara/teams","hooks_url":"https://api.github.com/repos/dthybert/ensembl-compara/hooks","issue_events_url":"https://api.github.com/repos/dthybert/ensembl-compara/issues/events{/number}","events_url":"https://api.github.com/repos/dthybert/ensembl-compara/events","assignees_url":"https://api.github.com/repos/dthybert/ensembl-compara/assignees{/user}","branches_url":"https://api.github.com/repos/dthybert/ensembl-compara/branches{/branch}","tags_url":"https://api.github.com/repos/dthybert/ensembl-compara/tags","blobs_url":"https://api.github.com/repos/dthybert/ensembl-compara/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dthybert/ensembl-compara/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dthybert/ensembl-compara/git/refs{/sha}","trees_url":"https://api.github.com/repos/dthybert/ensembl-compara/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dthybert/ensembl-compara/statuses/{sha}","languages_url":"https://api.github.com/repos/dthybert/ensembl-compara/languages","stargazers_url":"https://api.github.com/repos/dthybert/ensembl-compara/stargazers","contributors_url":"https://api.github.com/repos/dthybert/ensembl-compara/contributors","subscribers_url":"https://api.github.com/repos/dthybert/ensembl-compara/subscribers","subscription_url":"https://api.github.com/repos/dthybert/ensembl-compara/subscription","commits_url":"https://api.github.com/repos/dthybert/ensembl-compara/commits{/sha}","git_commits_url":"https://api.github.com/repos/dthybert/ensembl-compara/git/commits{/sha}","comments_url":"https://api.github.com/repos/dthybert/ensembl-compara/comments{/number}","issue_comment_url":"https://api.github.com/repos/dthybert/ensembl-compara/issues/comments{/number}","contents_url":"https://api.github.com/repos/dthybert/ensembl-compara/contents/{+path}","compare_url":"https://api.github.com/repos/dthybert/ensembl-compara/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dthybert/ensembl-compara/merges","archive_url":"https://api.github.com/repos/dthybert/ensembl-compara/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dthybert/ensembl-compara/downloads","issues_url":"https://api.github.com/repos/dthybert/ensembl-compara/issues{/number}","pulls_url":"https://api.github.com/repos/dthybert/ensembl-compara/pulls{/number}","milestones_url":"https://api.github.com/repos/dthybert/ensembl-compara/milestones{/number}","notifications_url":"https://api.github.com/repos/dthybert/ensembl-compara/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dthybert/ensembl-compara/labels{/name}","releases_url":"https://api.github.com/repos/dthybert/ensembl-compara/releases{/id}","deployments_url":"https://api.github.com/repos/dthybert/ensembl-compara/deployments","created_at":"2019-11-11T15:36:57Z","updated_at":"2019-11-11T15:36:59Z","pushed_at":"2019-11-12T13:48:57Z","git_url":"git://github.com/dthybert/ensembl-compara.git","ssh_url":"git@github.com:dthybert/ensembl-compara.git","clone_url":"https://github.com/dthybert/ensembl-compara.git","svn_url":"https://github.com/dthybert/ensembl-compara","homepage":"http://www.ensembl.org/info/docs/api/compara/","size":240725,"stargazers_count":0,"watchers_count":0,"language":null,"has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":0,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"release/98"}},"base":{"label":"Ensembl:dev/citest","ref":"dev/citest","sha":"50ea23b739e2ff94e9e2122bb6c322015e61e969","user":{"login":"Ensembl","id":5832463,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU4MzI0NjM=","avatar_url":"https://avatars3.githubusercontent.com/u/5832463?v=4","gravatar_id":"","url":"https://api.github.com/users/Ensembl","html_url":"https://github.com/Ensembl","followers_url":"https://api.github.com/users/Ensembl/followers","following_url":"https://api.github.com/users/Ensembl/following{/other_user}","gists_url":"https://api.github.com/users/Ensembl/gists{/gist_id}","starred_url":"https://api.github.com/users/Ensembl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Ensembl/subscriptions","organizations_url":"https://api.github.com/users/Ensembl/orgs","repos_url":"https://api.github.com/users/Ensembl/repos","events_url":"https://api.github.com/users/Ensembl/events{/privacy}","received_events_url":"https://api.github.com/users/Ensembl/received_events","type":"Organization","site_admin":false},"repo":{"id":14689025,"node_id":"MDEwOlJlcG9zaXRvcnkxNDY4OTAyNQ==","name":"ensembl-compara","full_name":"Ensembl/ensembl-compara","private":false,"owner":{"login":"Ensembl","id":5832463,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU4MzI0NjM=","avatar_url":"https://avatars3.githubusercontent.com/u/5832463?v=4","gravatar_id":"","url":"https://api.github.com/users/Ensembl","html_url":"https://github.com/Ensembl","followers_url":"https://api.github.com/users/Ensembl/followers","following_url":"https://api.github.com/users/Ensembl/following{/other_user}","gists_url":"https://api.github.com/users/Ensembl/gists{/gist_id}","starred_url":"https://api.github.com/users/Ensembl/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Ensembl/subscriptions","organizations_url":"https://api.github.com/users/Ensembl/orgs","repos_url":"https://api.github.com/users/Ensembl/repos","events_url":"https://api.github.com/users/Ensembl/events{/privacy}","received_events_url":"https://api.github.com/users/Ensembl/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/Ensembl/ensembl-compara","description":"The Ensembl Compara Perl API and SQL schema","fork":false,"url":"https://api.github.com/repos/Ensembl/ensembl-compara","forks_url":"https://api.github.com/repos/Ensembl/ensembl-compara/forks","keys_url":"https://api.github.com/repos/Ensembl/ensembl-compara/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Ensembl/ensembl-compara/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Ensembl/ensembl-compara/teams","hooks_url":"https://api.github.com/repos/Ensembl/ensembl-compara/hooks","issue_events_url":"https://api.github.com/repos/Ensembl/ensembl-compara/issues/events{/number}","events_url":"https://api.github.com/repos/Ensembl/ensembl-compara/events","assignees_url":"https://api.github.com/repos/Ensembl/ensembl-compara/assignees{/user}","branches_url":"https://api.github.com/repos/Ensembl/ensembl-compara/branches{/branch}","tags_url":"https://api.github.com/repos/Ensembl/ensembl-compara/tags","blobs_url":"https://api.github.com/repos/Ensembl/ensembl-compara/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Ensembl/ensembl-compara/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Ensembl/ensembl-compara/git/refs{/sha}","trees_url":"https://api.github.com/repos/Ensembl/ensembl-compara/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Ensembl/ensembl-compara/statuses/{sha}","languages_url":"https://api.github.com/repos/Ensembl/ensembl-compara/languages","stargazers_url":"https://api.github.com/repos/Ensembl/ensembl-compara/stargazers","contributors_url":"https://api.github.com/repos/Ensembl/ensembl-compara/contributors","subscribers_url":"https://api.github.com/repos/Ensembl/ensembl-compara/subscribers","subscription_url":"https://api.github.com/repos/Ensembl/ensembl-compara/subscription","commits_url":"https://api.github.com/repos/Ensembl/ensembl-compara/commits{/sha}","git_commits_url":"https://api.github.com/repos/Ensembl/ensembl-compara/git/commits{/sha}","comments_url":"https://api.github.com/repos/Ensembl/ensembl-compara/comments{/number}","issue_comment_url":"https://api.github.com/repos/Ensembl/ensembl-compara/issues/comments{/number}","contents_url":"https://api.github.com/repos/Ensembl/ensembl-compara/contents/{+path}","compare_url":"https://api.github.com/repos/Ensembl/ensembl-compara/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Ensembl/ensembl-compara/merges","archive_url":"https://api.github.com/repos/Ensembl/ensembl-compara/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Ensembl/ensembl-compara/downloads","issues_url":"https://api.github.com/repos/Ensembl/ensembl-compara/issues{/number}","pulls_url":"https://api.github.com/repos/Ensembl/ensembl-compara/pulls{/number}","milestones_url":"https://api.github.com/repos/Ensembl/ensembl-compara/milestones{/number}","notifications_url":"https://api.github.com/repos/Ensembl/ensembl-compara/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Ensembl/ensembl-compara/labels{/name}","releases_url":"https://api.github.com/repos/Ensembl/ensembl-compara/releases{/id}","deployments_url":"https://api.github.com/repos/Ensembl/ensembl-compara/deployments","created_at":"2013-11-25T15:18:17Z","updated_at":"2019-11-02T22:31:21Z","pushed_at":"2019-11-18T08:48:07Z","git_url":"git://github.com/Ensembl/ensembl-compara.git","ssh_url":"git@github.com:Ensembl/ensembl-compara.git","clone_url":"https://github.com/Ensembl/ensembl-compara.git","svn_url":"https://github.com/Ensembl/ensembl-compara","homepage":"http://www.ensembl.org/info/docs/api/compara/","size":240848,"stargazers_count":30,"watchers_count":30,"language":"Perl","has_issues":false,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":51,"mirror_url":null,"archived":false,"disabled":false,"open_issues_count":4,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":51,"open_issues":4,"watchers":30,"default_branch":"release/98"}},"_links":{"self":{"href":"https://api.github.com/repos/Ensembl/ensembl-compara/pulls/157"},"html":{"href":"https://github.com/Ensembl/ensembl-compara/pull/157"},"issue":{"href":"https://api.github.com/repos/Ensembl/ensembl-compara/issues/157"},"comments":{"href":"https://api.github.com/repos/Ensembl/ensembl-compara/issues/157/comments"},"review_comments":{"href":"https://api.github.com/repos/Ensembl/ensembl-compara/pulls/157/comments"},"review_comment":{"href":"https://api.github.com/repos/Ensembl/ensembl-compara/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Ensembl/ensembl-compara/pulls/157/commits"},"statuses":{"href":"https://api.github.com/repos/Ensembl/ensembl-compara/statuses/67aa149696ac9a1185e9954590b3cd3c6aea9687"}},"author_association":"NONE"}}
{"actor":{"display_login":"carlacummins"}}