{"action":"created","comment":{"url":"https://api.github.com/repos/biocore/scikit-bio/pulls/comments/65107694","id":65107694,"diff_hunk":"@@ -0,0 +1,334 @@\n+# ----------------------------------------------------------------------------\n+# Copyright (c) 2013--, scikit-bio development team.\n+#\n+# Distributed under the terms of the Modified BSD License.\n+#\n+# The full license is in the file COPYING.txt, distributed with this software.\n+# ----------------------------------------------------------------------------\n+\n+from ._intersection import IntervalTree\n+\n+\n+class Interval():\n+    '''Stores the position and metadata of an interval.\n+\n+    Parameters\n+    ----------\n+    intervals : list of tuple of ints\n+        List of tuples representing start and end coordinates.\n+    boundaries : list of tuple of bool\n+        List of tuples, representing the openness of each interval.\n+    metadata : dict\n+        Dictionary of attributes storing information of the feature\n+        such as `strand`, `gene_name` or `product`.\n+    interval_metadata : object\n+        A reference to the `IntervalMetadata` object that this\n+        interval is associated to.\n+    '''\n+    def __init__(self, intervals=None, boundaries=None,\n+                 metadata=None, interval_metadata=None):\n+        iv = []\n+        for interval in intervals:\n+            iv.append(_polish_interval(interval))\n+\n+        if boundaries is not None:\n+            self.boundaries = boundaries\n+        else:\n+            self.boundaries = []\n+\n+        if metadata is not None:\n+            self.metadata = metadata\n+        else:\n+            self.metadata = {}\n+\n+        self._interval_metadata = interval_metadata\n+\n+        if intervals is not None:\n+            self.intervals = sorted(iv)\n+        else:\n+            self.intervals = []\n+\n+        if interval_metadata is not None:\n+            self._add_interval()\n+\n+    def _add_interval(self):\n+        \"\"\" Add an interval object to the IntervalTree within\n+            IntervalMetadata.\"\"\"\n+        # Add directly to the tree.  So no need for _is_stale_tree\n+        for loc in self.intervals:\n+            if loc is not None:\n+                start, end = loc\n+                self._interval_metadata._intervals.add(start, end, self)\n+        self._interval_metadata._metadata.append(self)\n+\n+    def __getitem__(self, key):\n+        return self.metadata[key]\n+\n+    def __setitem__(self, key, val):\n+        self.metadata[key] = val\n+\n+    # This is required for creating unique sets of intervals\n+    def __hash__(self):\n+        return hash(tuple(sorted(self.metadata.items()) +\n+                          self.intervals +\n+                          self.boundaries))\n+\n+    def __lt__(self, other):\n+        return self.intervals < other.intervals\n+\n+    def __gt__(self, other):\n+        return self.intervals > other.intervals\n+\n+    def __le__(self, other):\n+        return self.intervals <= other.intervals\n+\n+    def __ge__(self, other):\n+        return self.intervals >= other.intervals\n+\n+    def __eq__(self, other):\n+        return ((self.metadata == other.metadata) and\n+                (self.intervals == other.intervals) and\n+                (self.boundaries == other.boundaries))\n+\n+    def __contains__(self, key):\n+        return key in self.metadata\n+\n+    def __ne__(self, other):\n+        return not self.__eq__(other)\n+\n+    def __repr__(self):\n+        return ''.join([\n+            \"Interval(\"\n+            \"intervals=\" + str(self.intervals),\n+            \", metadata=\" + str(self.metadata),\n+            \")\"])\n+\n+    def drop(self):\n+        self._interval_metadata.drop(intervals=self.intervals,\n+                                     boundaries=self.boundaries,\n+                                     metadata=self.metadata)\n+        self.boundaries = None\n+        self.intervals = None\n+        self._interval_metadata = None\n+\n+    @property\n+    def intervals(self):\n+        return self._intervals\n+\n+    @intervals.setter\n+    def intervals(self, value):\n+        self._intervals = value\n+        if self._interval_metadata is not None:\n+            self._interval_metadata._is_stale_tree = True\n+\n+\n+class IntervalMetadata():\n+    \"\"\" Stores Interval objects \"\"\"\n+    def __init__(self):\n+        # stores metadata for each feature\n+        self._metadata = []\n+        self._intervals = IntervalTree()\n+        self._is_stale_tree = False\n+\n+    def _reverse(self, length):\n+        \"\"\" Reverse complements IntervalMetadata object.\n+\n+        This operation reverses all of the interval coordinates.\n+        For instance, this can be used to compare coordinates\n+        in the forward strand to coordinates in the reversal strand.\n+\n+        Parameters\n+        ----------\n+        length : int\n+            Largest end coordinate to perform reverse complement.\n+            This typically corresponds to the length of sequence.\n+        \"\"\"\n+        for f in self._metadata:\n+            # staled doesn't need to be called, since the setter for\n+            # Interval will take care of this\n+            invs = list(map(lambda x: (length-x[1], length-x[0]),\n+                            f.intervals))\n+            f.intervals = invs\n+\n+    def add(self, intervals, boundaries=None, metadata=None):\n+        \"\"\" Adds a feature to the metadata object.\n+\n+        Parameters\n+        ----------\n+        intervals : iterable of tuple of ints\n+            A list of intervals associated with the Interval object.\n+        boundaries : iterable of tuple of bool\n+            A list of boundaries associated with the Interval object.\n+        metadata : dict\n+            A dictionary of key word attributes associated with the\n+            Interval object.\n+\n+        Examples\n+        --------\n+        >>> from skbio.metadata import IntervalMetadata\n+        >>> interval_metadata = IntervalMetadata()\n+        >>> interval_metadata.add(intervals=[(0, 2), (4, 7)],\n+        ...                       boundaries=None, metadata={'name': 'sagA'})\n+        >>> interval_metadata.add(intervals=[(40, 70)],\n+        ...                       boundaries=None, metadata={'name': 'sagB'})\n+        >>> interval_metadata.query(intervals=[(1, 2)])\n+        [Interval(intervals=[(0, 2), (4, 7)], metadata={'name': 'sagA'})]\n+\n+        \"\"\"\n+        # Add an interval to the tree. Note that the add functionality is\n+        # built within the Interval constructor.\n+        Interval(interval_metadata=self,\n+                 intervals=intervals,\n+                 boundaries=boundaries,\n+                 metadata=metadata)\n+\n+    def _rebuild_tree(self, intervals):\n+        \"\"\" Rebuilds the IntervalTree when the tree is stale.\"\"\"\n+        self._intervals = IntervalTree()\n+        for f in intervals:\n+            for inv in f.intervals:\n+                start, end = inv\n+                self._intervals.add(start, end, f)\n+\n+    def _query_interval(self, interval):\n+        \"\"\" Fetches Interval objects based on query interval\"\"\"\n+        start, end = _polish_interval(interval)\n+        invs = self._intervals.find(start, end)\n+        return invs\n+\n+    def _query_attribute(self, intervals, metadata):\n+        \"\"\" Fetches Interval objects based on query attributes\"\"\"\n+        if metadata is None:\n+            return []\n+\n+        queries = []\n+        for inv in intervals:\n+            for (key, value) in metadata.items():\n+                if inv[key] != value:\n+                    continue\n+                queries.append(inv)\n+        return queries\n+\n+    def query(self, intervals=None, boundaries=None, metadata=None):\n+        \"\"\" Looks up Interval objects with the intervals, boundaries and keywords.\n+\n+        Parameters\n+        ----------\n+        intervals : iterable of tuple of ints\n+            A list of intervals associated with the Interval object.\n+        boundaries : iterable of tuple of bool\n+            A list of boundaries associated with the Interval object.\n+        metadata : dict\n+            A dictionary of key word attributes associated with the\n+            Interval object.\n+\n+        Returns\n+        -------\n+        list, Interval\n+            A list of Interval objects satisfying the search criteria.\n+\n+        Examples\n+        --------\n+        >>> from skbio.metadata import IntervalMetadata\n+        >>> interval_metadata = IntervalMetadata()\n+        >>> interval_metadata.add(intervals=[(0, 2), (4, 7)],\n+        ...                       boundaries=None, metadata={'name': 'sagA'})\n+        >>> interval_metadata.add(intervals=[(40, 70)],\n+        ...                       boundaries=None, metadata={'name': 'sagB'})\n+        >>> interval_metadata.query(intervals=[(1, 2)])\n+        [Interval(intervals=[(0, 2), (4, 7)], metadata={'name': 'sagA'})]\n+\n+        Note\n+        ----\n+        There are two types of queries to perform\n+        1. Query by interval.\n+        2. Query by key/val pair (i.e. gene=sagA).\n+\n+        \"\"\"\n+        if self._is_stale_tree:\n+            self._rebuild_tree(self._metadata)\n+            self._is_stale_tree = False\n+\n+        invs = set()\n+\n+        # Find queries by interval\n+        if intervals is not None:\n+            for value in intervals:\n+                invs.update(self._query_interval(value))\n+\n+        # Find queries by feature attribute\n+        if len(invs) == 0 and metadata is not None:\n+            invs = set(self._metadata)\n+\n+        if metadata is not None:\n+            invs = self._query_attribute(invs, metadata)\n+        return list(invs)\n+\n+    def drop(self, intervals=None, boundaries=None, metadata=None):\n+        \"\"\" Drops Interval objects according to a specified query.\n+\n+        Drops all Interval objects that matches the query.\n+\n+        Parameters\n+        ----------\n+        intervals : iterable of tuple of ints\n+            A list of intervals associated with the Interval object.\n+        boundaries : iterable of tuple of bool\n+            A list of boundaries associated with the Interval object.\n+        metadata : dict\n+            A dictionary of key word attributes associated with the\n+            Interval object.\n+\n+        Examples\n+        --------\n+        >>> from skbio.metadata import IntervalMetadata\n+        >>> interval_metadata = IntervalMetadata()\n+        >>> interval_metadata.add(intervals=[(0, 2), (4, 7)],\n+        ...                       boundaries=None, metadata={'name': 'sagA'})\n+        >>> interval_metadata.add(intervals=[(40, 70)],\n+        ...                       boundaries=None, metadata={'name': 'sagB'})\n+        >>> interval_metadata.drop(metadata={'name': 'sagA'})\n+        >>> interval_metadata.query(metadata={'name': 'sagA'})\n+        []\n+        \"\"\"\n+        if intervals is None:\n+            intervals = []\n+        if metadata is None:\n+            metadata = {}\n+\n+        queried_invs = self.query(intervals=intervals,\n+                                  boundaries=boundaries,\n+                                  metadata=metadata)\n+        new_invs = []\n+        # iterate through queries and drop them\n+        for inv in self._metadata:\n+            if inv not in queried_invs:\n+                new_invs.append(inv)\n+        self._metadata = new_invs\n+        self._is_stale_tree = True\n+\n+    def __eq__(self, other):\n+        return sorted(self._metadata) == sorted(other._metadata)\n+\n+    def __ne__(self, other):\n+        return not self.__eq__(other)\n+\n+    def __repr__(self):\n+        if len(self._metadata) < 10:\n+            return str(self._metadata)\n+        else:\n+            return str(self._metadata[:5] + ['...'] + self._metadata[-5:])\n+\n+\n+def _polish_interval(interval):\n+    if isinstance(interval, tuple):\n+        if len(interval) == 0:\n+            return None\n+        if len(interval) == 2:\n+            start, end = interval\n+        else:\n+            raise ValueError(\"`start` and `end` aren't correctly specified\")\n+    else:\n+        raise ValueError('The args must be associated with '","path":"skbio/metadata/_interval.py","position":null,"original_position":332,"commit_id":"a42a841cc570a5b76c272cae3a038671f8bfa25a","original_commit_id":"82ffdeb392ae0f4104cc071cb5811cd92a802ed7","user":{"login":"mortonjt","id":4184797,"avatar_url":"https://avatars.githubusercontent.com/u/4184797?v=3","gravatar_id":"","url":"https://api.github.com/users/mortonjt","html_url":"https://github.com/mortonjt","followers_url":"https://api.github.com/users/mortonjt/followers","following_url":"https://api.github.com/users/mortonjt/following{/other_user}","gists_url":"https://api.github.com/users/mortonjt/gists{/gist_id}","starred_url":"https://api.github.com/users/mortonjt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mortonjt/subscriptions","organizations_url":"https://api.github.com/users/mortonjt/orgs","repos_url":"https://api.github.com/users/mortonjt/repos","events_url":"https://api.github.com/users/mortonjt/events{/privacy}","received_events_url":"https://api.github.com/users/mortonjt/received_events","type":"User","site_admin":false},"body":"Hope this is ok\r\n\r\n```python\r\n        raise TypeError('The interval must be associated with '\r\n                        'a tuple.')\r\n\r\n```","created_at":"2016-05-30T21:50:02Z","updated_at":"2016-05-30T21:50:02Z","html_url":"https://github.com/biocore/scikit-bio/pull/1356#discussion_r65107694","pull_request_url":"https://api.github.com/repos/biocore/scikit-bio/pulls/1356","_links":{"self":{"href":"https://api.github.com/repos/biocore/scikit-bio/pulls/comments/65107694"},"html":{"href":"https://github.com/biocore/scikit-bio/pull/1356#discussion_r65107694"},"pull_request":{"href":"https://api.github.com/repos/biocore/scikit-bio/pulls/1356"}}},"pull_request":{"url":"https://api.github.com/repos/biocore/scikit-bio/pulls/1356","id":70451506,"html_url":"https://github.com/biocore/scikit-bio/pull/1356","diff_url":"https://github.com/biocore/scikit-bio/pull/1356.diff","patch_url":"https://github.com/biocore/scikit-bio/pull/1356.patch","issue_url":"https://api.github.com/repos/biocore/scikit-bio/issues/1356","number":1356,"state":"open","locked":false,"title":"Interval metadata Part 1","user":{"login":"mortonjt","id":4184797,"avatar_url":"https://avatars.githubusercontent.com/u/4184797?v=3","gravatar_id":"","url":"https://api.github.com/users/mortonjt","html_url":"https://github.com/mortonjt","followers_url":"https://api.github.com/users/mortonjt/followers","following_url":"https://api.github.com/users/mortonjt/following{/other_user}","gists_url":"https://api.github.com/users/mortonjt/gists{/gist_id}","starred_url":"https://api.github.com/users/mortonjt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mortonjt/subscriptions","organizations_url":"https://api.github.com/users/mortonjt/orgs","repos_url":"https://api.github.com/users/mortonjt/repos","events_url":"https://api.github.com/users/mortonjt/events{/privacy}","received_events_url":"https://api.github.com/users/mortonjt/received_events","type":"User","site_admin":false},"body":"Here's the Interval Metadata object proposed from the RFC.\r\n\r\nNow, this PR is only accounting for the IntervalMetadata object, the Interval and IntervalTree objects.\r\nThere are a few parsers in micronota that depend on having just the IntervalMetadata object completed.\r\n\r\nSo, I'm thinking about getting the `IntervalMetadataMixin` in after this PR.  Does that sound reasonable?","created_at":"2016-05-18T00:13:32Z","updated_at":"2016-05-30T21:50:02Z","closed_at":null,"merged_at":null,"merge_commit_sha":"671489f1a56925f51e077e23a475a02a9bfa73b5","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/biocore/scikit-bio/pulls/1356/commits","review_comments_url":"https://api.github.com/repos/biocore/scikit-bio/pulls/1356/comments","review_comment_url":"https://api.github.com/repos/biocore/scikit-bio/pulls/comments{/number}","comments_url":"https://api.github.com/repos/biocore/scikit-bio/issues/1356/comments","statuses_url":"https://api.github.com/repos/biocore/scikit-bio/statuses/a42a841cc570a5b76c272cae3a038671f8bfa25a","head":{"label":"mortonjt:interval_metadata_new_part1","ref":"interval_metadata_new_part1","sha":"a42a841cc570a5b76c272cae3a038671f8bfa25a","user":{"login":"mortonjt","id":4184797,"avatar_url":"https://avatars.githubusercontent.com/u/4184797?v=3","gravatar_id":"","url":"https://api.github.com/users/mortonjt","html_url":"https://github.com/mortonjt","followers_url":"https://api.github.com/users/mortonjt/followers","following_url":"https://api.github.com/users/mortonjt/following{/other_user}","gists_url":"https://api.github.com/users/mortonjt/gists{/gist_id}","starred_url":"https://api.github.com/users/mortonjt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mortonjt/subscriptions","organizations_url":"https://api.github.com/users/mortonjt/orgs","repos_url":"https://api.github.com/users/mortonjt/repos","events_url":"https://api.github.com/users/mortonjt/events{/privacy}","received_events_url":"https://api.github.com/users/mortonjt/received_events","type":"User","site_admin":false},"repo":{"id":23898042,"name":"scikit-bio","full_name":"mortonjt/scikit-bio","owner":{"login":"mortonjt","id":4184797,"avatar_url":"https://avatars.githubusercontent.com/u/4184797?v=3","gravatar_id":"","url":"https://api.github.com/users/mortonjt","html_url":"https://github.com/mortonjt","followers_url":"https://api.github.com/users/mortonjt/followers","following_url":"https://api.github.com/users/mortonjt/following{/other_user}","gists_url":"https://api.github.com/users/mortonjt/gists{/gist_id}","starred_url":"https://api.github.com/users/mortonjt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mortonjt/subscriptions","organizations_url":"https://api.github.com/users/mortonjt/orgs","repos_url":"https://api.github.com/users/mortonjt/repos","events_url":"https://api.github.com/users/mortonjt/events{/privacy}","received_events_url":"https://api.github.com/users/mortonjt/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mortonjt/scikit-bio","description":"Core objects, functions and statistics for working with biological data in Python.","fork":true,"url":"https://api.github.com/repos/mortonjt/scikit-bio","forks_url":"https://api.github.com/repos/mortonjt/scikit-bio/forks","keys_url":"https://api.github.com/repos/mortonjt/scikit-bio/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mortonjt/scikit-bio/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mortonjt/scikit-bio/teams","hooks_url":"https://api.github.com/repos/mortonjt/scikit-bio/hooks","issue_events_url":"https://api.github.com/repos/mortonjt/scikit-bio/issues/events{/number}","events_url":"https://api.github.com/repos/mortonjt/scikit-bio/events","assignees_url":"https://api.github.com/repos/mortonjt/scikit-bio/assignees{/user}","branches_url":"https://api.github.com/repos/mortonjt/scikit-bio/branches{/branch}","tags_url":"https://api.github.com/repos/mortonjt/scikit-bio/tags","blobs_url":"https://api.github.com/repos/mortonjt/scikit-bio/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mortonjt/scikit-bio/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mortonjt/scikit-bio/git/refs{/sha}","trees_url":"https://api.github.com/repos/mortonjt/scikit-bio/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mortonjt/scikit-bio/statuses/{sha}","languages_url":"https://api.github.com/repos/mortonjt/scikit-bio/languages","stargazers_url":"https://api.github.com/repos/mortonjt/scikit-bio/stargazers","contributors_url":"https://api.github.com/repos/mortonjt/scikit-bio/contributors","subscribers_url":"https://api.github.com/repos/mortonjt/scikit-bio/subscribers","subscription_url":"https://api.github.com/repos/mortonjt/scikit-bio/subscription","commits_url":"https://api.github.com/repos/mortonjt/scikit-bio/commits{/sha}","git_commits_url":"https://api.github.com/repos/mortonjt/scikit-bio/git/commits{/sha}","comments_url":"https://api.github.com/repos/mortonjt/scikit-bio/comments{/number}","issue_comment_url":"https://api.github.com/repos/mortonjt/scikit-bio/issues/comments{/number}","contents_url":"https://api.github.com/repos/mortonjt/scikit-bio/contents/{+path}","compare_url":"https://api.github.com/repos/mortonjt/scikit-bio/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mortonjt/scikit-bio/merges","archive_url":"https://api.github.com/repos/mortonjt/scikit-bio/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mortonjt/scikit-bio/downloads","issues_url":"https://api.github.com/repos/mortonjt/scikit-bio/issues{/number}","pulls_url":"https://api.github.com/repos/mortonjt/scikit-bio/pulls{/number}","milestones_url":"https://api.github.com/repos/mortonjt/scikit-bio/milestones{/number}","notifications_url":"https://api.github.com/repos/mortonjt/scikit-bio/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mortonjt/scikit-bio/labels{/name}","releases_url":"https://api.github.com/repos/mortonjt/scikit-bio/releases{/id}","deployments_url":"https://api.github.com/repos/mortonjt/scikit-bio/deployments","created_at":"2014-09-11T00:39:57Z","updated_at":"2016-02-11T20:54:32Z","pushed_at":"2016-05-28T18:22:27Z","git_url":"git://github.com/mortonjt/scikit-bio.git","ssh_url":"git@github.com:mortonjt/scikit-bio.git","clone_url":"https://github.com/mortonjt/scikit-bio.git","svn_url":"https://github.com/mortonjt/scikit-bio","homepage":"http://scikit-bio.org","size":36103,"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:master","ref":"master","sha":"87d577a1ba30215cac508d6496b45fbfefd9347e","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":15168264,"name":"scikit-bio","full_name":"biocore/scikit-bio","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/scikit-bio","description":"scikit-bio is an open-source, BSD-licensed, Python package providing data structures, algorithms, and educational resources for bioinformatics.","fork":false,"url":"https://api.github.com/repos/biocore/scikit-bio","forks_url":"https://api.github.com/repos/biocore/scikit-bio/forks","keys_url":"https://api.github.com/repos/biocore/scikit-bio/keys{/key_id}","collaborators_url":"https://api.github.com/repos/biocore/scikit-bio/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/biocore/scikit-bio/teams","hooks_url":"https://api.github.com/repos/biocore/scikit-bio/hooks","issue_events_url":"https://api.github.com/repos/biocore/scikit-bio/issues/events{/number}","events_url":"https://api.github.com/repos/biocore/scikit-bio/events","assignees_url":"https://api.github.com/repos/biocore/scikit-bio/assignees{/user}","branches_url":"https://api.github.com/repos/biocore/scikit-bio/branches{/branch}","tags_url":"https://api.github.com/repos/biocore/scikit-bio/tags","blobs_url":"https://api.github.com/repos/biocore/scikit-bio/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/biocore/scikit-bio/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/biocore/scikit-bio/git/refs{/sha}","trees_url":"https://api.github.com/repos/biocore/scikit-bio/git/trees{/sha}","statuses_url":"https://api.github.com/repos/biocore/scikit-bio/statuses/{sha}","languages_url":"https://api.github.com/repos/biocore/scikit-bio/languages","stargazers_url":"https://api.github.com/repos/biocore/scikit-bio/stargazers","contributors_url":"https://api.github.com/repos/biocore/scikit-bio/contributors","subscribers_url":"https://api.github.com/repos/biocore/scikit-bio/subscribers","subscription_url":"https://api.github.com/repos/biocore/scikit-bio/subscription","commits_url":"https://api.github.com/repos/biocore/scikit-bio/commits{/sha}","git_commits_url":"https://api.github.com/repos/biocore/scikit-bio/git/commits{/sha}","comments_url":"https://api.github.com/repos/biocore/scikit-bio/comments{/number}","issue_comment_url":"https://api.github.com/repos/biocore/scikit-bio/issues/comments{/number}","contents_url":"https://api.github.com/repos/biocore/scikit-bio/contents/{+path}","compare_url":"https://api.github.com/repos/biocore/scikit-bio/compare/{base}...{head}","merges_url":"https://api.github.com/repos/biocore/scikit-bio/merges","archive_url":"https://api.github.com/repos/biocore/scikit-bio/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/biocore/scikit-bio/downloads","issues_url":"https://api.github.com/repos/biocore/scikit-bio/issues{/number}","pulls_url":"https://api.github.com/repos/biocore/scikit-bio/pulls{/number}","milestones_url":"https://api.github.com/repos/biocore/scikit-bio/milestones{/number}","notifications_url":"https://api.github.com/repos/biocore/scikit-bio/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/biocore/scikit-bio/labels{/name}","releases_url":"https://api.github.com/repos/biocore/scikit-bio/releases{/id}","deployments_url":"https://api.github.com/repos/biocore/scikit-bio/deployments","created_at":"2013-12-13T16:24:41Z","updated_at":"2016-05-25T05:16:59Z","pushed_at":"2016-05-28T18:22:31Z","git_url":"git://github.com/biocore/scikit-bio.git","ssh_url":"git@github.com:biocore/scikit-bio.git","clone_url":"https://github.com/biocore/scikit-bio.git","svn_url":"https://github.com/biocore/scikit-bio","homepage":"http://scikit-bio.org","size":42017,"stargazers_count":211,"watchers_count":211,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":95,"mirror_url":null,"open_issues_count":170,"forks":95,"open_issues":170,"watchers":211,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/biocore/scikit-bio/pulls/1356"},"html":{"href":"https://github.com/biocore/scikit-bio/pull/1356"},"issue":{"href":"https://api.github.com/repos/biocore/scikit-bio/issues/1356"},"comments":{"href":"https://api.github.com/repos/biocore/scikit-bio/issues/1356/comments"},"review_comments":{"href":"https://api.github.com/repos/biocore/scikit-bio/pulls/1356/comments"},"review_comment":{"href":"https://api.github.com/repos/biocore/scikit-bio/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/biocore/scikit-bio/pulls/1356/commits"},"statuses":{"href":"https://api.github.com/repos/biocore/scikit-bio/statuses/a42a841cc570a5b76c272cae3a038671f8bfa25a"}}}}
{"actor":{"display_login":"mortonjt"}}