{"action":"created","comment":{"url":"https://api.github.com/repos/prestodb/presto-admin/pulls/comments/46736873","id":46736873,"diff_hunk":"@@ -0,0 +1,189 @@\n+# -*- coding: utf-8 -*-\n+#\n+# Licensed under the Apache License, Version 2.0 (the \"License\");\n+# you may not use this file except in compliance with the License.\n+# You may obtain a copy of the License at\n+#\n+# http://www.apache.org/licenses/LICENSE-2.0\n+#\n+# Unless required by applicable law or agreed to in writing, software\n+# distributed under the License is distributed on an \"AS IS\" BASIS,\n+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+# See the License for the specific language governing permissions and\n+# limitations under the License.\n+\n+\"\"\"\n+Stuff to handle version ranges.\n+\"\"\"\n+\n+import re\n+\n+TD_VERSION = re.compile(r'^\\d+t$')\n+ANCIENT_TAGGED_VERSION = re.compile(r'^\\d+t?-[A-Z]+$')\n+\n+\n+def split_version(version_string):\n+    return version_string.strip().split('.')\n+\n+\n+def strip_tag(version):\n+    \"\"\"\n+    Strip trailing non-numeric components from a version leaving the Teradata\n+    't' on the final version component if it's present.\n+    ['1', '2', 'THREE'] -> (1, 2)\n+    ['1', 'TWO', '3'] -> raises a ValueError\n+    ['0', '115t', 'SNAPSHOT'] -> (0, '115t')\n+    ['ZERO', '123t'] -> raises a ValueError\n+    :param version: something that can be sliced\n+    :return: a tuple containing only integer components, except for possibly\n+             the last one, which will be a string iff it's an integer followed\n+             by the letter 't'\n+    \"\"\"\n+    is_teradata = False\n+    is_ancient = False\n+\n+    result = list(version[:])\n+    while True:\n+        try:\n+            last = result[-1]\n+            int(last)\n+            break\n+        except ValueError:\n+            if ANCIENT_TAGGED_VERSION.match(last):\n+                is_ancient = True\n+                result[-1] = last.split('-')[0]\n+\n+            # Do this second, and get the last component by index to get the\n+            # updated value for an ancient tagged version\n+            if TD_VERSION.match(result[-1]):\n+                is_teradata = True\n+                break\n+\n+            # Non-teradata ancient tag.\n+            if is_ancient:\n+                break\n+            result = result[:-1]\n+        except IndexError:\n+            raise ValueError(\n+                '%s does not contain any numeric version information' %\n+                (version,))\n+\n+    if is_teradata:\n+        result = [int(x) for x in result[:-1]] + [result[-1]]\n+    else:\n+        result = [int(x) for x in result]\n+\n+    return tuple(result)\n+\n+\n+class VersionRange(object):\n+    \"\"\"\n+    Represents a range of version numbers [min_version, max_version).\n+    The interval is right-open so that you can construct a numerically\n+    continuous list of versions like so:\n+    l = [VersionRange((0, 0), (0, 5)),\n+         VersionRange((0, 5), (1, 0))]\n+    and for all versions v where 0.0 <= v < 1.0 is contained in exactly one\n+    VersionRange in l.\n+\n+    Continuity between version ranges can be checked using is_continuous.\n+\n+    VersionRanges understand how to check if a Teradata version is contained\n+    in a VersionRange, but do no special handling to accomodate Teradata\n+    versions in their internal min_version and max_version members. I.e.,\n+    creating a VersionRange with a Teradata version will work, but __contains__\n+    will not work correctly. We don't currently need this, and hope not to.\n+\n+    Note that the right-open interval representation of a version range does\n+    NOT allow the creation of a VersionRange that contains exactly one version.\n+\n+    Note that empty intervals cannot be constructed as the serve no useful\n+    purpose. Specifically, we assert that min_version < max_version in the\n+    constructor.\n+    \"\"\"\n+\n+    def __init__(self, min_version, max_version, versioned_thing=None):\n+        # not pythonic, but bare ints screw things up.\n+        assert isinstance(min_version, tuple)\n+        assert isinstance(max_version, tuple)\n+        l = max(len(min_version), len(max_version))\n+        min_pad = VersionRange.pad_tuple(min_version, l, 0)\n+        max_pad = VersionRange.pad_tuple(max_version, l, 0)\n+        assert min_pad < max_pad\n+        self.min_version = min_version\n+        self.max_version = max_version\n+        self.versioned_thing = versioned_thing\n+\n+    def __str__(self):\n+        return '[%s, %s) -> %s' % (\n+            '.'.join([str(c) for c in self.min_version]),\n+            '.'.join([str(c) for c in self.max_version]),\n+            self.versioned_thing)\n+\n+    @staticmethod\n+    def strip_td_suffix(other):\n+        last_component = other[-1]\n+        if isinstance(last_component, int):\n+            return other\n+\n+        if TD_VERSION.match(last_component):\n+            new_last = last_component[:-1]\n+            return other[:-1] + (int(new_last),)\n+\n+        return other\n+\n+    @staticmethod\n+    def pad_tuple(tup, length, pad):\n+        assert len(tup) <= length\n+        result = list(tup)\n+        while len(result) < length:\n+            result.append(pad)\n+        return tuple(result)\n+\n+    def zero_pad(self, other):\n+        \"\"\"\n+        Pad out min_version, max_version, and other with zeroes to the length\n+        of the longest of the three. This allows subsequent comparisons to work\n+        as expected when tuples are of unequal length.\n+        Returns a tuple of tuples padded out to the same length\n+        \"\"\"\n+        l = max(len(self.min_version), len(self.max_version), len(other))\n+        return (self.pad_tuple(self.min_version, l, 0),\n+                self.pad_tuple(self.max_version, l, 0),\n+                self.pad_tuple(other, l, 0))\n+\n+    def __contains__(self, other):\n+        other = self.strip_td_suffix(other)\n+        other = tuple([int(component) for component in other])\n+\n+        min_pad, max_pad, o_pad = self.zero_pad(other)\n+        return min_pad <= o_pad and o_pad < max_pad\n+\n+    def is_continuous(self, next):","path":"prestoadmin/util/version_util.py","position":162,"original_position":162,"commit_id":"b41e6acc8a72b40ba6b9c8e5dd9729f51c9783f7","original_commit_id":"b41e6acc8a72b40ba6b9c8e5dd9729f51c9783f7","user":{"login":"cawallin","id":3652644,"avatar_url":"https://avatars.githubusercontent.com/u/3652644?v=3","gravatar_id":"","url":"https://api.github.com/users/cawallin","html_url":"https://github.com/cawallin","followers_url":"https://api.github.com/users/cawallin/followers","following_url":"https://api.github.com/users/cawallin/following{/other_user}","gists_url":"https://api.github.com/users/cawallin/gists{/gist_id}","starred_url":"https://api.github.com/users/cawallin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cawallin/subscriptions","organizations_url":"https://api.github.com/users/cawallin/orgs","repos_url":"https://api.github.com/users/cawallin/repos","events_url":"https://api.github.com/users/cawallin/events{/privacy}","received_events_url":"https://api.github.com/users/cawallin/received_events","type":"User","site_admin":false},"body":"why isn't the next argument used?","created_at":"2015-12-04T21:52:33Z","updated_at":"2015-12-04T21:52:33Z","html_url":"https://github.com/prestodb/presto-admin/pull/96#discussion_r46736873","pull_request_url":"https://api.github.com/repos/prestodb/presto-admin/pulls/96","_links":{"self":{"href":"https://api.github.com/repos/prestodb/presto-admin/pulls/comments/46736873"},"html":{"href":"https://github.com/prestodb/presto-admin/pull/96#discussion_r46736873"},"pull_request":{"href":"https://api.github.com/repos/prestodb/presto-admin/pulls/96"}}},"pull_request":{"url":"https://api.github.com/repos/prestodb/presto-admin/pulls/96","id":52720237,"html_url":"https://github.com/prestodb/presto-admin/pull/96","diff_url":"https://github.com/prestodb/presto-admin/pull/96.diff","patch_url":"https://github.com/prestodb/presto-admin/pull/96.patch","issue_url":"https://api.github.com/repos/prestodb/presto-admin/issues/96","number":96,"state":"open","locked":false,"title":"Fix server status for presto >= 0.128","user":{"login":"ebd2","id":12751788,"avatar_url":"https://avatars.githubusercontent.com/u/12751788?v=3","gravatar_id":"","url":"https://api.github.com/users/ebd2","html_url":"https://github.com/ebd2","followers_url":"https://api.github.com/users/ebd2/followers","following_url":"https://api.github.com/users/ebd2/following{/other_user}","gists_url":"https://api.github.com/users/ebd2/gists{/gist_id}","starred_url":"https://api.github.com/users/ebd2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ebd2/subscriptions","organizations_url":"https://api.github.com/users/ebd2/orgs","repos_url":"https://api.github.com/users/ebd2/repos","events_url":"https://api.github.com/users/ebd2/events{/privacy}","received_events_url":"https://api.github.com/users/ebd2/received_events","type":"User","site_admin":false},"body":"The release of presto 0.128 changed the name of a column we were querying in the implementation of presto-admin server-status.\r\nFixing the issue involves running a different query against presto depending on the version.\r\nEnsuring consistent output regardless of version requires processing the results of the query differently, again depending on the version.\r\n\r\nAs part of the work to fix this, I added in general tooling to handle version-based issues. This isn't the first time we've needed to change the behavior of something based on the version, and it surely won't be the last.\r\n\r\nI plan to leave this as two separate commits, as the version functionality is independently useful.","created_at":"2015-12-04T20:55:55Z","updated_at":"2015-12-04T21:52:33Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c0399b9f85b9da7672c6d4c5397d184ec2501930","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/prestodb/presto-admin/pulls/96/commits","review_comments_url":"https://api.github.com/repos/prestodb/presto-admin/pulls/96/comments","review_comment_url":"https://api.github.com/repos/prestodb/presto-admin/pulls/comments{/number}","comments_url":"https://api.github.com/repos/prestodb/presto-admin/issues/96/comments","statuses_url":"https://api.github.com/repos/prestodb/presto-admin/statuses/b41e6acc8a72b40ba6b9c8e5dd9729f51c9783f7","head":{"label":"prestodb:fix-status","ref":"fix-status","sha":"b41e6acc8a72b40ba6b9c8e5dd9729f51c9783f7","user":{"login":"prestodb","id":6882181,"avatar_url":"https://avatars.githubusercontent.com/u/6882181?v=3","gravatar_id":"","url":"https://api.github.com/users/prestodb","html_url":"https://github.com/prestodb","followers_url":"https://api.github.com/users/prestodb/followers","following_url":"https://api.github.com/users/prestodb/following{/other_user}","gists_url":"https://api.github.com/users/prestodb/gists{/gist_id}","starred_url":"https://api.github.com/users/prestodb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/prestodb/subscriptions","organizations_url":"https://api.github.com/users/prestodb/orgs","repos_url":"https://api.github.com/users/prestodb/repos","events_url":"https://api.github.com/users/prestodb/events{/privacy}","received_events_url":"https://api.github.com/users/prestodb/received_events","type":"Organization","site_admin":false},"repo":{"id":36050721,"name":"presto-admin","full_name":"prestodb/presto-admin","owner":{"login":"prestodb","id":6882181,"avatar_url":"https://avatars.githubusercontent.com/u/6882181?v=3","gravatar_id":"","url":"https://api.github.com/users/prestodb","html_url":"https://github.com/prestodb","followers_url":"https://api.github.com/users/prestodb/followers","following_url":"https://api.github.com/users/prestodb/following{/other_user}","gists_url":"https://api.github.com/users/prestodb/gists{/gist_id}","starred_url":"https://api.github.com/users/prestodb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/prestodb/subscriptions","organizations_url":"https://api.github.com/users/prestodb/orgs","repos_url":"https://api.github.com/users/prestodb/repos","events_url":"https://api.github.com/users/prestodb/events{/privacy}","received_events_url":"https://api.github.com/users/prestodb/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/prestodb/presto-admin","description":"A tool to install, configure and manage Presto installations","fork":false,"url":"https://api.github.com/repos/prestodb/presto-admin","forks_url":"https://api.github.com/repos/prestodb/presto-admin/forks","keys_url":"https://api.github.com/repos/prestodb/presto-admin/keys{/key_id}","collaborators_url":"https://api.github.com/repos/prestodb/presto-admin/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/prestodb/presto-admin/teams","hooks_url":"https://api.github.com/repos/prestodb/presto-admin/hooks","issue_events_url":"https://api.github.com/repos/prestodb/presto-admin/issues/events{/number}","events_url":"https://api.github.com/repos/prestodb/presto-admin/events","assignees_url":"https://api.github.com/repos/prestodb/presto-admin/assignees{/user}","branches_url":"https://api.github.com/repos/prestodb/presto-admin/branches{/branch}","tags_url":"https://api.github.com/repos/prestodb/presto-admin/tags","blobs_url":"https://api.github.com/repos/prestodb/presto-admin/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/prestodb/presto-admin/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/prestodb/presto-admin/git/refs{/sha}","trees_url":"https://api.github.com/repos/prestodb/presto-admin/git/trees{/sha}","statuses_url":"https://api.github.com/repos/prestodb/presto-admin/statuses/{sha}","languages_url":"https://api.github.com/repos/prestodb/presto-admin/languages","stargazers_url":"https://api.github.com/repos/prestodb/presto-admin/stargazers","contributors_url":"https://api.github.com/repos/prestodb/presto-admin/contributors","subscribers_url":"https://api.github.com/repos/prestodb/presto-admin/subscribers","subscription_url":"https://api.github.com/repos/prestodb/presto-admin/subscription","commits_url":"https://api.github.com/repos/prestodb/presto-admin/commits{/sha}","git_commits_url":"https://api.github.com/repos/prestodb/presto-admin/git/commits{/sha}","comments_url":"https://api.github.com/repos/prestodb/presto-admin/comments{/number}","issue_comment_url":"https://api.github.com/repos/prestodb/presto-admin/issues/comments{/number}","contents_url":"https://api.github.com/repos/prestodb/presto-admin/contents/{+path}","compare_url":"https://api.github.com/repos/prestodb/presto-admin/compare/{base}...{head}","merges_url":"https://api.github.com/repos/prestodb/presto-admin/merges","archive_url":"https://api.github.com/repos/prestodb/presto-admin/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/prestodb/presto-admin/downloads","issues_url":"https://api.github.com/repos/prestodb/presto-admin/issues{/number}","pulls_url":"https://api.github.com/repos/prestodb/presto-admin/pulls{/number}","milestones_url":"https://api.github.com/repos/prestodb/presto-admin/milestones{/number}","notifications_url":"https://api.github.com/repos/prestodb/presto-admin/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/prestodb/presto-admin/labels{/name}","releases_url":"https://api.github.com/repos/prestodb/presto-admin/releases{/id}","created_at":"2015-05-22T03:40:42Z","updated_at":"2015-11-19T15:15:49Z","pushed_at":"2015-12-04T21:29:38Z","git_url":"git://github.com/prestodb/presto-admin.git","ssh_url":"git@github.com:prestodb/presto-admin.git","clone_url":"https://github.com/prestodb/presto-admin.git","svn_url":"https://github.com/prestodb/presto-admin","homepage":"http://prestodb.github.io/presto-admin/","size":39098,"stargazers_count":32,"watchers_count":32,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":8,"mirror_url":null,"open_issues_count":12,"forks":8,"open_issues":12,"watchers":32,"default_branch":"master"}},"base":{"label":"prestodb:master","ref":"master","sha":"f31675805a802a117b691e2b1ee60421999889f0","user":{"login":"prestodb","id":6882181,"avatar_url":"https://avatars.githubusercontent.com/u/6882181?v=3","gravatar_id":"","url":"https://api.github.com/users/prestodb","html_url":"https://github.com/prestodb","followers_url":"https://api.github.com/users/prestodb/followers","following_url":"https://api.github.com/users/prestodb/following{/other_user}","gists_url":"https://api.github.com/users/prestodb/gists{/gist_id}","starred_url":"https://api.github.com/users/prestodb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/prestodb/subscriptions","organizations_url":"https://api.github.com/users/prestodb/orgs","repos_url":"https://api.github.com/users/prestodb/repos","events_url":"https://api.github.com/users/prestodb/events{/privacy}","received_events_url":"https://api.github.com/users/prestodb/received_events","type":"Organization","site_admin":false},"repo":{"id":36050721,"name":"presto-admin","full_name":"prestodb/presto-admin","owner":{"login":"prestodb","id":6882181,"avatar_url":"https://avatars.githubusercontent.com/u/6882181?v=3","gravatar_id":"","url":"https://api.github.com/users/prestodb","html_url":"https://github.com/prestodb","followers_url":"https://api.github.com/users/prestodb/followers","following_url":"https://api.github.com/users/prestodb/following{/other_user}","gists_url":"https://api.github.com/users/prestodb/gists{/gist_id}","starred_url":"https://api.github.com/users/prestodb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/prestodb/subscriptions","organizations_url":"https://api.github.com/users/prestodb/orgs","repos_url":"https://api.github.com/users/prestodb/repos","events_url":"https://api.github.com/users/prestodb/events{/privacy}","received_events_url":"https://api.github.com/users/prestodb/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/prestodb/presto-admin","description":"A tool to install, configure and manage Presto installations","fork":false,"url":"https://api.github.com/repos/prestodb/presto-admin","forks_url":"https://api.github.com/repos/prestodb/presto-admin/forks","keys_url":"https://api.github.com/repos/prestodb/presto-admin/keys{/key_id}","collaborators_url":"https://api.github.com/repos/prestodb/presto-admin/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/prestodb/presto-admin/teams","hooks_url":"https://api.github.com/repos/prestodb/presto-admin/hooks","issue_events_url":"https://api.github.com/repos/prestodb/presto-admin/issues/events{/number}","events_url":"https://api.github.com/repos/prestodb/presto-admin/events","assignees_url":"https://api.github.com/repos/prestodb/presto-admin/assignees{/user}","branches_url":"https://api.github.com/repos/prestodb/presto-admin/branches{/branch}","tags_url":"https://api.github.com/repos/prestodb/presto-admin/tags","blobs_url":"https://api.github.com/repos/prestodb/presto-admin/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/prestodb/presto-admin/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/prestodb/presto-admin/git/refs{/sha}","trees_url":"https://api.github.com/repos/prestodb/presto-admin/git/trees{/sha}","statuses_url":"https://api.github.com/repos/prestodb/presto-admin/statuses/{sha}","languages_url":"https://api.github.com/repos/prestodb/presto-admin/languages","stargazers_url":"https://api.github.com/repos/prestodb/presto-admin/stargazers","contributors_url":"https://api.github.com/repos/prestodb/presto-admin/contributors","subscribers_url":"https://api.github.com/repos/prestodb/presto-admin/subscribers","subscription_url":"https://api.github.com/repos/prestodb/presto-admin/subscription","commits_url":"https://api.github.com/repos/prestodb/presto-admin/commits{/sha}","git_commits_url":"https://api.github.com/repos/prestodb/presto-admin/git/commits{/sha}","comments_url":"https://api.github.com/repos/prestodb/presto-admin/comments{/number}","issue_comment_url":"https://api.github.com/repos/prestodb/presto-admin/issues/comments{/number}","contents_url":"https://api.github.com/repos/prestodb/presto-admin/contents/{+path}","compare_url":"https://api.github.com/repos/prestodb/presto-admin/compare/{base}...{head}","merges_url":"https://api.github.com/repos/prestodb/presto-admin/merges","archive_url":"https://api.github.com/repos/prestodb/presto-admin/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/prestodb/presto-admin/downloads","issues_url":"https://api.github.com/repos/prestodb/presto-admin/issues{/number}","pulls_url":"https://api.github.com/repos/prestodb/presto-admin/pulls{/number}","milestones_url":"https://api.github.com/repos/prestodb/presto-admin/milestones{/number}","notifications_url":"https://api.github.com/repos/prestodb/presto-admin/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/prestodb/presto-admin/labels{/name}","releases_url":"https://api.github.com/repos/prestodb/presto-admin/releases{/id}","created_at":"2015-05-22T03:40:42Z","updated_at":"2015-11-19T15:15:49Z","pushed_at":"2015-12-04T21:29:38Z","git_url":"git://github.com/prestodb/presto-admin.git","ssh_url":"git@github.com:prestodb/presto-admin.git","clone_url":"https://github.com/prestodb/presto-admin.git","svn_url":"https://github.com/prestodb/presto-admin","homepage":"http://prestodb.github.io/presto-admin/","size":39098,"stargazers_count":32,"watchers_count":32,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":8,"mirror_url":null,"open_issues_count":12,"forks":8,"open_issues":12,"watchers":32,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/prestodb/presto-admin/pulls/96"},"html":{"href":"https://github.com/prestodb/presto-admin/pull/96"},"issue":{"href":"https://api.github.com/repos/prestodb/presto-admin/issues/96"},"comments":{"href":"https://api.github.com/repos/prestodb/presto-admin/issues/96/comments"},"review_comments":{"href":"https://api.github.com/repos/prestodb/presto-admin/pulls/96/comments"},"review_comment":{"href":"https://api.github.com/repos/prestodb/presto-admin/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/prestodb/presto-admin/pulls/96/commits"},"statuses":{"href":"https://api.github.com/repos/prestodb/presto-admin/statuses/b41e6acc8a72b40ba6b9c8e5dd9729f51c9783f7"}}}}