{"action":"created","comment":{"url":"https://api.github.com/repos/CartoDB/bigmetadata/pulls/comments/191433271","pull_request_review_id":124003167,"id":191433271,"diff_hunk":"@@ -0,0 +1,179 @@\n+from tasks.us.census.tiger import ShorelineClip\n+from tasks.targets import PostgresTarget\n+from luigi import IntParameter, Parameter, WrapperTask, Task\n+from tasks.meta import current_session, async_pool\n+from lib.logger import get_logger\n+from lib.tileutils import tile2bounds\n+from lib.geo import bboxes_intersect\n+import json\n+import os\n+import time\n+import asyncio\n+import concurrent.futures\n+import backoff\n+import csv\n+\n+LOGGER = get_logger(__name__)\n+\n+\n+class TilerXYZTableTask(Task):\n+\n+    zoom_level = IntParameter()\n+    geography = Parameter()\n+\n+    def __init__(self, *args, **kwargs):\n+        super(TilerXYZTableTask, self).__init__(*args, **kwargs)\n+        self.config_data = self._get_config_data()\n+        if not os.path.exists('tmp/tiler'):\n+            os.makedirs('tmp/tiler')\n+        self._csv_filename = 'tmp/tiler/tile_{}.csv'.format(self.task_id)\n+\n+    def get_config_file(self):\n+        raise NotImplementedError('Config file must be implemented by the child class')\n+\n+    def get_geography_level(self, level):\n+        raise NotImplementedError('Geography levels file must be implemented by the child class')\n+\n+    def requires(self):\n+        return {\n+            'shorelineclip': ShorelineClip(geography=self.geography, year='2015')\n+        }\n+\n+    def run(self):\n+        config_data = self._get_config_data()\n+        for table_config in config_data:\n+            table_schema = self._get_table_schema(table_config)\n+            table_bboxes = table_config['bboxes']\n+            self._create_schema_and_table(table_schema)\n+            self._generate_and_insert_tiles(self.zoom_level, table_schema, table_config['columns'], table_bboxes)\n+\n+    def _create_schema_and_table(self, table_schema):\n+        session = current_session()\n+        session.execute('CREATE SCHEMA IF NOT EXISTS tiler')\n+        cols_schema = []\n+        table_name = \"{}.{}\".format(table_schema['schema'], table_schema['table_name'])\n+        for _, cols in table_schema['columns'].items():\n+            cols_schema += cols\n+        sql_table = '''CREATE TABLE IF NOT EXISTS {}(\n+                x INTEGER NOT NULL,\n+                y INTEGER NOT NULL,\n+                z INTEGER NOT NULL,\n+                mvt_geometry Geometry NOT NULL,\n+                geoid VARCHAR NOT NULL,\n+                area_ratio NUMERIC,\n+                {},\n+                CONSTRAINT xyzusall_pk PRIMARY KEY (x,y,z,geoid)\n+            )'''.format(table_name, \", \".join(cols_schema))\n+        session.execute(sql_table)\n+        session.commit()\n+\n+    def _get_config_data(self):\n+        dir_path = os.path.dirname(os.path.realpath(__file__))\n+        with (open('{}/conf/{}'.format(dir_path, self.get_config_file()))) as f:\n+            return json.load(f)\n+\n+    def _get_table_schema(self, table_config):\n+        columns = {}\n+        for dataset, col_data in table_config['columns'].items():\n+            columns[dataset] = []\n+            for column in col_data:\n+                nullable = '' if column['nullable'] else 'NOT NULL'\n+                columns[dataset].append(\"{} {} {}\".format(column['column_name'], column['type'], nullable))\n+        return {\"schema\": table_config['schema'], \"table_name\": table_config['table'], \"columns\": columns}\n+\n+    def _tile_in_bboxes(self, zoom, x, y, bboxes):\n+        rect1 = tile2bounds(zoom, x, y)\n+        for bbox in bboxes:\n+            rect2 = [bbox['xmin'], bbox['ymin'], bbox['xmax'], bbox['ymax']]\n+            if bboxes_intersect(rect1, rect2):\n+                return True\n+\n+        return False\n+\n+    def _generate_and_insert_tiles(self, zoom, table_schema, columns_config, bboxes_config):\n+        table_name = \"{}.{}\".format(table_schema['schema'], table_schema['table_name'])\n+        do_columns = [column['id'] for column in columns_config['do']]\n+        mc_columns = [column['id'] for column in columns_config['mc']]\n+        recordset = [\"mvtdata->>'id' as id\"]\n+        recordset.append(\"(mvtdata->>'area_ratio')::numeric as area_ratio\")\n+        for _, columns in columns_config.items():\n+            recordset += [\"(mvtdata->>'{}')::{} as {}\".format(column['column_name'], column['type'], column['column_name']) for column in columns]\n+        tiles = []\n+        tile_start = time.time()\n+        for x in range(0, (pow(2, zoom) + 1)):\n+            for y in range(0, (pow(2, zoom) + 1)):\n+                if self._tile_in_bboxes(zoom, x, y, bboxes_config):\n+                    tiles.append([x, y, zoom])\n+        tile_end = time.time()\n+        LOGGER.info(\"Tiles to be processed: {} tiles. Calculated in {} seconds\".format(len(tiles), (tile_end - tile_start)))\n+        sql_start = time.time()\n+        loop = asyncio.new_event_loop()\n+        asyncio.set_event_loop(loop)\n+        try:\n+            exceptions = loop.run_until_complete(self._generate_tiles(tiles, recordset, do_columns, mc_columns))\n+            if exceptions:\n+                LOGGER.warning(\"Exception/s found processing tiles: {}\".format(\"\\n\".join([e for e in exceptions if e is not None])))\n+        finally:\n+            loop.close()\n+        sql_end = time.time()\n+        LOGGER.info(\"Generation tiles time was {} seconds\".format(sql_end - sql_start))\n+        self._insert_tiles(table_name)\n+\n+    @backoff.on_exception(backoff.expo,\n+                          (asyncio.TimeoutError,\n+                           concurrent.futures._base.TimeoutError),\n+                          max_time=600)\n+    async def _generate_tiles(self, tiles, recordset, do_columns, mc_columns):\n+        with open(self._csv_filename, 'w+') as csvfile:\n+            db_pool = await async_pool()\n+            csvwriter = csv.writer(csvfile)\n+            geography_level = self.get_geography_level(self.geography)\n+            executed_tiles = [self._generate_tile(db_pool, csvwriter, tile, geography_level, recordset, do_columns, mc_columns) for tile in tiles]\n+            exceptions = await asyncio.gather(*executed_tiles, return_exceptions=True)\n+            return exceptions\n+\n+    @backoff.on_exception(backoff.expo,\n+                          (asyncio.TimeoutError,\n+                           concurrent.futures._base.TimeoutError),\n+                          max_time=600)\n+    async def _generate_tile(self, db_pool, csvwriter, tile, geography, recordset, do_columns, mc_columns):\n+        sql_tile = '''\n+            SELECT {x}, {y}, {z}, ST_CollectionExtract(ST_MakeValid(mvtgeom), 3) mvtgeom, {recordset}\n+            FROM cdb_observatory.OBS_GetMCDOMVT({z},{x},{y},'{geography_level}',ARRAY['{docols}']::TEXT[],ARRAY['{mccols}']::TEXT[])\n+            WHERE mvtgeom IS NOT NULL;\n+            '''.format(x=tile[0], y=tile[1], z=tile[2], geography_level=geography,\n+                       recordset=\", \".join(recordset), docols=\"', '\".join(do_columns),\n+                       mccols=\"', '\".join(mc_columns))\n+        conn = None\n+        try:\n+            conn = await db_pool.acquire()\n+            tile_start = time.time()\n+            records = await conn.fetch(sql_tile)\n+            tile_end = time.time()\n+            LOGGER.debug('Generated tile [{}/{}/{}] in {} seconds'.format(tile[0], tile[1], tile[2], (tile_end - tile_start)))\n+            for record in records:\n+                csvwriter.writerow(tuple(record))\n+            else:\n+                LOGGER.debug('Tile [{}/{}/{}] without data'.format(tile[0], tile[1], tile[2], (tile_end - tile_start)))\n+        except BaseException as e:\n+            LOGGER.error('Tile [{}/{}/{}] returned exception {}'.format(tile[0], tile[1], tile[2], e))\n+            raise e\n+        finally:\n+            await db_pool.release(conn)\n+\n+    def _insert_tiles(self, table_name):\n+        copy_start = time.time()\n+        session = current_session()\n+        with open(self._csv_filename,'rb') as f:\n+            cursor = session.connection().connection.cursor()\n+            cursor.copy_from(f, table_name, sep=',', null='')\n+            session.commit()\n+        copy_end = time.time()\n+        LOGGER.info(\"Copy tiles time was {} seconds\".format(copy_end - copy_start))\n+\n+    def output(self):\n+        targets = []\n+        for table_config in self.config_data:\n+            table_schema = self._get_table_schema(table_config)\n+            targets.append(PostgresTarget(table_schema['schema'], table_schema['table_name'], where='z = {}'.format(self.zoom_level)))","path":"tasks/tiler/xyz.py","position":178,"original_position":178,"commit_id":"c0320d89b3b6f132cdc7b288660fd91bea157443","original_commit_id":"c0320d89b3b6f132cdc7b288660fd91bea157443","user":{"login":"houndci-bot","id":6697940,"avatar_url":"https://avatars0.githubusercontent.com/u/6697940?v=4","gravatar_id":"","url":"https://api.github.com/users/houndci-bot","html_url":"https://github.com/houndci-bot","followers_url":"https://api.github.com/users/houndci-bot/followers","following_url":"https://api.github.com/users/houndci-bot/following{/other_user}","gists_url":"https://api.github.com/users/houndci-bot/gists{/gist_id}","starred_url":"https://api.github.com/users/houndci-bot/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/houndci-bot/subscriptions","organizations_url":"https://api.github.com/users/houndci-bot/orgs","repos_url":"https://api.github.com/users/houndci-bot/repos","events_url":"https://api.github.com/users/houndci-bot/events{/privacy}","received_events_url":"https://api.github.com/users/houndci-bot/received_events","type":"User","site_admin":false},"body":"line too long (134 > 120 characters)","created_at":"2018-05-29T13:56:23Z","updated_at":"2018-05-29T13:56:24Z","html_url":"https://github.com/CartoDB/bigmetadata/pull/495#discussion_r191433271","pull_request_url":"https://api.github.com/repos/CartoDB/bigmetadata/pulls/495","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/CartoDB/bigmetadata/pulls/comments/191433271"},"html":{"href":"https://github.com/CartoDB/bigmetadata/pull/495#discussion_r191433271"},"pull_request":{"href":"https://api.github.com/repos/CartoDB/bigmetadata/pulls/495"}}},"pull_request":{"url":"https://api.github.com/repos/CartoDB/bigmetadata/pulls/495","id":189402857,"html_url":"https://github.com/CartoDB/bigmetadata/pull/495","diff_url":"https://github.com/CartoDB/bigmetadata/pull/495.diff","patch_url":"https://github.com/CartoDB/bigmetadata/pull/495.patch","issue_url":"https://api.github.com/repos/CartoDB/bigmetadata/issues/495","number":495,"state":"open","locked":false,"title":"Xyz tables generation","user":{"login":"ethervoid","id":741240,"avatar_url":"https://avatars3.githubusercontent.com/u/741240?v=4","gravatar_id":"","url":"https://api.github.com/users/ethervoid","html_url":"https://github.com/ethervoid","followers_url":"https://api.github.com/users/ethervoid/followers","following_url":"https://api.github.com/users/ethervoid/following{/other_user}","gists_url":"https://api.github.com/users/ethervoid/gists{/gist_id}","starred_url":"https://api.github.com/users/ethervoid/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ethervoid/subscriptions","organizations_url":"https://api.github.com/users/ethervoid/orgs","repos_url":"https://api.github.com/users/ethervoid/repos","events_url":"https://api.github.com/users/ethervoid/events{/privacy}","received_events_url":"https://api.github.com/users/ethervoid/received_events","type":"User","site_admin":false},"body":"","created_at":"2018-05-21T14:55:27Z","updated_at":"2018-05-29T13:56:24Z","closed_at":null,"merged_at":null,"merge_commit_sha":"433900b6fb23c1297240825b24dad2dde5d395fb","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/CartoDB/bigmetadata/pulls/495/commits","review_comments_url":"https://api.github.com/repos/CartoDB/bigmetadata/pulls/495/comments","review_comment_url":"https://api.github.com/repos/CartoDB/bigmetadata/pulls/comments{/number}","comments_url":"https://api.github.com/repos/CartoDB/bigmetadata/issues/495/comments","statuses_url":"https://api.github.com/repos/CartoDB/bigmetadata/statuses/c0320d89b3b6f132cdc7b288660fd91bea157443","head":{"label":"CartoDB:xyz_tables_generation","ref":"xyz_tables_generation","sha":"c0320d89b3b6f132cdc7b288660fd91bea157443","user":{"login":"CartoDB","id":1799254,"avatar_url":"https://avatars0.githubusercontent.com/u/1799254?v=4","gravatar_id":"","url":"https://api.github.com/users/CartoDB","html_url":"https://github.com/CartoDB","followers_url":"https://api.github.com/users/CartoDB/followers","following_url":"https://api.github.com/users/CartoDB/following{/other_user}","gists_url":"https://api.github.com/users/CartoDB/gists{/gist_id}","starred_url":"https://api.github.com/users/CartoDB/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CartoDB/subscriptions","organizations_url":"https://api.github.com/users/CartoDB/orgs","repos_url":"https://api.github.com/users/CartoDB/repos","events_url":"https://api.github.com/users/CartoDB/events{/privacy}","received_events_url":"https://api.github.com/users/CartoDB/received_events","type":"Organization","site_admin":false},"repo":{"id":47357348,"name":"bigmetadata","full_name":"CartoDB/bigmetadata","owner":{"login":"CartoDB","id":1799254,"avatar_url":"https://avatars0.githubusercontent.com/u/1799254?v=4","gravatar_id":"","url":"https://api.github.com/users/CartoDB","html_url":"https://github.com/CartoDB","followers_url":"https://api.github.com/users/CartoDB/followers","following_url":"https://api.github.com/users/CartoDB/following{/other_user}","gists_url":"https://api.github.com/users/CartoDB/gists{/gist_id}","starred_url":"https://api.github.com/users/CartoDB/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CartoDB/subscriptions","organizations_url":"https://api.github.com/users/CartoDB/orgs","repos_url":"https://api.github.com/users/CartoDB/repos","events_url":"https://api.github.com/users/CartoDB/events{/privacy}","received_events_url":"https://api.github.com/users/CartoDB/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/CartoDB/bigmetadata","description":null,"fork":false,"url":"https://api.github.com/repos/CartoDB/bigmetadata","forks_url":"https://api.github.com/repos/CartoDB/bigmetadata/forks","keys_url":"https://api.github.com/repos/CartoDB/bigmetadata/keys{/key_id}","collaborators_url":"https://api.github.com/repos/CartoDB/bigmetadata/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/CartoDB/bigmetadata/teams","hooks_url":"https://api.github.com/repos/CartoDB/bigmetadata/hooks","issue_events_url":"https://api.github.com/repos/CartoDB/bigmetadata/issues/events{/number}","events_url":"https://api.github.com/repos/CartoDB/bigmetadata/events","assignees_url":"https://api.github.com/repos/CartoDB/bigmetadata/assignees{/user}","branches_url":"https://api.github.com/repos/CartoDB/bigmetadata/branches{/branch}","tags_url":"https://api.github.com/repos/CartoDB/bigmetadata/tags","blobs_url":"https://api.github.com/repos/CartoDB/bigmetadata/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/CartoDB/bigmetadata/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/CartoDB/bigmetadata/git/refs{/sha}","trees_url":"https://api.github.com/repos/CartoDB/bigmetadata/git/trees{/sha}","statuses_url":"https://api.github.com/repos/CartoDB/bigmetadata/statuses/{sha}","languages_url":"https://api.github.com/repos/CartoDB/bigmetadata/languages","stargazers_url":"https://api.github.com/repos/CartoDB/bigmetadata/stargazers","contributors_url":"https://api.github.com/repos/CartoDB/bigmetadata/contributors","subscribers_url":"https://api.github.com/repos/CartoDB/bigmetadata/subscribers","subscription_url":"https://api.github.com/repos/CartoDB/bigmetadata/subscription","commits_url":"https://api.github.com/repos/CartoDB/bigmetadata/commits{/sha}","git_commits_url":"https://api.github.com/repos/CartoDB/bigmetadata/git/commits{/sha}","comments_url":"https://api.github.com/repos/CartoDB/bigmetadata/comments{/number}","issue_comment_url":"https://api.github.com/repos/CartoDB/bigmetadata/issues/comments{/number}","contents_url":"https://api.github.com/repos/CartoDB/bigmetadata/contents/{+path}","compare_url":"https://api.github.com/repos/CartoDB/bigmetadata/compare/{base}...{head}","merges_url":"https://api.github.com/repos/CartoDB/bigmetadata/merges","archive_url":"https://api.github.com/repos/CartoDB/bigmetadata/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/CartoDB/bigmetadata/downloads","issues_url":"https://api.github.com/repos/CartoDB/bigmetadata/issues{/number}","pulls_url":"https://api.github.com/repos/CartoDB/bigmetadata/pulls{/number}","milestones_url":"https://api.github.com/repos/CartoDB/bigmetadata/milestones{/number}","notifications_url":"https://api.github.com/repos/CartoDB/bigmetadata/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/CartoDB/bigmetadata/labels{/name}","releases_url":"https://api.github.com/repos/CartoDB/bigmetadata/releases{/id}","deployments_url":"https://api.github.com/repos/CartoDB/bigmetadata/deployments","created_at":"2015-12-03T20:09:45Z","updated_at":"2018-05-15T15:19:27Z","pushed_at":"2018-05-29T13:56:06Z","git_url":"git://github.com/CartoDB/bigmetadata.git","ssh_url":"git@github.com:CartoDB/bigmetadata.git","clone_url":"https://github.com/CartoDB/bigmetadata.git","svn_url":"https://github.com/CartoDB/bigmetadata","homepage":null,"size":671805,"stargazers_count":31,"watchers_count":31,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":6,"mirror_url":null,"archived":false,"open_issues_count":117,"license":{"key":"bsd-3-clause","name":"BSD 3-Clause \"New\" or \"Revised\" License","spdx_id":"BSD-3-Clause","url":"https://api.github.com/licenses/bsd-3-clause"},"forks":6,"open_issues":117,"watchers":31,"default_branch":"master"}},"base":{"label":"CartoDB:master","ref":"master","sha":"ef9ecc1baed17edf1ccc3798543f8250912ed47c","user":{"login":"CartoDB","id":1799254,"avatar_url":"https://avatars0.githubusercontent.com/u/1799254?v=4","gravatar_id":"","url":"https://api.github.com/users/CartoDB","html_url":"https://github.com/CartoDB","followers_url":"https://api.github.com/users/CartoDB/followers","following_url":"https://api.github.com/users/CartoDB/following{/other_user}","gists_url":"https://api.github.com/users/CartoDB/gists{/gist_id}","starred_url":"https://api.github.com/users/CartoDB/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CartoDB/subscriptions","organizations_url":"https://api.github.com/users/CartoDB/orgs","repos_url":"https://api.github.com/users/CartoDB/repos","events_url":"https://api.github.com/users/CartoDB/events{/privacy}","received_events_url":"https://api.github.com/users/CartoDB/received_events","type":"Organization","site_admin":false},"repo":{"id":47357348,"name":"bigmetadata","full_name":"CartoDB/bigmetadata","owner":{"login":"CartoDB","id":1799254,"avatar_url":"https://avatars0.githubusercontent.com/u/1799254?v=4","gravatar_id":"","url":"https://api.github.com/users/CartoDB","html_url":"https://github.com/CartoDB","followers_url":"https://api.github.com/users/CartoDB/followers","following_url":"https://api.github.com/users/CartoDB/following{/other_user}","gists_url":"https://api.github.com/users/CartoDB/gists{/gist_id}","starred_url":"https://api.github.com/users/CartoDB/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CartoDB/subscriptions","organizations_url":"https://api.github.com/users/CartoDB/orgs","repos_url":"https://api.github.com/users/CartoDB/repos","events_url":"https://api.github.com/users/CartoDB/events{/privacy}","received_events_url":"https://api.github.com/users/CartoDB/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/CartoDB/bigmetadata","description":null,"fork":false,"url":"https://api.github.com/repos/CartoDB/bigmetadata","forks_url":"https://api.github.com/repos/CartoDB/bigmetadata/forks","keys_url":"https://api.github.com/repos/CartoDB/bigmetadata/keys{/key_id}","collaborators_url":"https://api.github.com/repos/CartoDB/bigmetadata/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/CartoDB/bigmetadata/teams","hooks_url":"https://api.github.com/repos/CartoDB/bigmetadata/hooks","issue_events_url":"https://api.github.com/repos/CartoDB/bigmetadata/issues/events{/number}","events_url":"https://api.github.com/repos/CartoDB/bigmetadata/events","assignees_url":"https://api.github.com/repos/CartoDB/bigmetadata/assignees{/user}","branches_url":"https://api.github.com/repos/CartoDB/bigmetadata/branches{/branch}","tags_url":"https://api.github.com/repos/CartoDB/bigmetadata/tags","blobs_url":"https://api.github.com/repos/CartoDB/bigmetadata/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/CartoDB/bigmetadata/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/CartoDB/bigmetadata/git/refs{/sha}","trees_url":"https://api.github.com/repos/CartoDB/bigmetadata/git/trees{/sha}","statuses_url":"https://api.github.com/repos/CartoDB/bigmetadata/statuses/{sha}","languages_url":"https://api.github.com/repos/CartoDB/bigmetadata/languages","stargazers_url":"https://api.github.com/repos/CartoDB/bigmetadata/stargazers","contributors_url":"https://api.github.com/repos/CartoDB/bigmetadata/contributors","subscribers_url":"https://api.github.com/repos/CartoDB/bigmetadata/subscribers","subscription_url":"https://api.github.com/repos/CartoDB/bigmetadata/subscription","commits_url":"https://api.github.com/repos/CartoDB/bigmetadata/commits{/sha}","git_commits_url":"https://api.github.com/repos/CartoDB/bigmetadata/git/commits{/sha}","comments_url":"https://api.github.com/repos/CartoDB/bigmetadata/comments{/number}","issue_comment_url":"https://api.github.com/repos/CartoDB/bigmetadata/issues/comments{/number}","contents_url":"https://api.github.com/repos/CartoDB/bigmetadata/contents/{+path}","compare_url":"https://api.github.com/repos/CartoDB/bigmetadata/compare/{base}...{head}","merges_url":"https://api.github.com/repos/CartoDB/bigmetadata/merges","archive_url":"https://api.github.com/repos/CartoDB/bigmetadata/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/CartoDB/bigmetadata/downloads","issues_url":"https://api.github.com/repos/CartoDB/bigmetadata/issues{/number}","pulls_url":"https://api.github.com/repos/CartoDB/bigmetadata/pulls{/number}","milestones_url":"https://api.github.com/repos/CartoDB/bigmetadata/milestones{/number}","notifications_url":"https://api.github.com/repos/CartoDB/bigmetadata/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/CartoDB/bigmetadata/labels{/name}","releases_url":"https://api.github.com/repos/CartoDB/bigmetadata/releases{/id}","deployments_url":"https://api.github.com/repos/CartoDB/bigmetadata/deployments","created_at":"2015-12-03T20:09:45Z","updated_at":"2018-05-15T15:19:27Z","pushed_at":"2018-05-29T13:56:06Z","git_url":"git://github.com/CartoDB/bigmetadata.git","ssh_url":"git@github.com:CartoDB/bigmetadata.git","clone_url":"https://github.com/CartoDB/bigmetadata.git","svn_url":"https://github.com/CartoDB/bigmetadata","homepage":null,"size":671805,"stargazers_count":31,"watchers_count":31,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":6,"mirror_url":null,"archived":false,"open_issues_count":117,"license":{"key":"bsd-3-clause","name":"BSD 3-Clause \"New\" or \"Revised\" License","spdx_id":"BSD-3-Clause","url":"https://api.github.com/licenses/bsd-3-clause"},"forks":6,"open_issues":117,"watchers":31,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/CartoDB/bigmetadata/pulls/495"},"html":{"href":"https://github.com/CartoDB/bigmetadata/pull/495"},"issue":{"href":"https://api.github.com/repos/CartoDB/bigmetadata/issues/495"},"comments":{"href":"https://api.github.com/repos/CartoDB/bigmetadata/issues/495/comments"},"review_comments":{"href":"https://api.github.com/repos/CartoDB/bigmetadata/pulls/495/comments"},"review_comment":{"href":"https://api.github.com/repos/CartoDB/bigmetadata/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/CartoDB/bigmetadata/pulls/495/commits"},"statuses":{"href":"https://api.github.com/repos/CartoDB/bigmetadata/statuses/c0320d89b3b6f132cdc7b288660fd91bea157443"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"houndci-bot"}}