{"action":"created","comment":{"url":"https://api.github.com/repos/PulpQE/pulp-smash/pulls/comments/44332722","id":44332722,"diff_hunk":"@@ -0,0 +1,336 @@\n+# coding=utf-8\n+\"\"\"Test Pulp's `Searching`_ facilities.\n+\n+The tests in this module make use of the `User APIs`_. However, few\n+user-specific references are made. These tests could be rewritten to use\n+repositories or something else with only minimal changes. Thus, the name of\n+this module.\n+\n+Each test case executes one or more pairs of semantically identical POST and\n+GET requests. Each pair of search results should match exactly.\n+\n+Most test cases assume that the assertions in some other test case hold true.\n+The assumptions explored in this module have the following dependencies::\n+\n+    It is possible to ask for all resources of a kind.\n+    ├── It is possible to sort search results.\n+    ├── It is possible to ask for a single field in search results.\n+    ├── It is possible to ask for several fields in search results.\n+    └── It is possible to ask for a resource with a specific ID.\n+        └── It is possible to ask for a resource with one of several IDs.\n+            ├── It is possible to skip some search results.\n+            └── It is possible to limit how many search results are returned.\n+\n+.. _Searching:\n+    https://pulp.readthedocs.org/en/latest/dev-guide/conventions/criteria.html\n+.. _User APIs:\n+    https://pulp.readthedocs.org/en/latest/dev-guide/integration/rest-api/user/index.html\n+\n+\"\"\"\n+from __future__ import unicode_literals\n+\n+import requests\n+from pulp_smash.config import get_config\n+from pulp_smash.constants import USER_PATH\n+from random import randint\n+from unittest2 import TestCase\n+\n+from sys import version_info\n+if version_info.major == 2:\n+    from urllib import urlencode  # pylint:disable=no-name-in-module\n+else:\n+    from urllib.parse import urlencode  # noqa pylint:disable=no-name-in-module,import-error\n+\n+\n+_SEARCH_PATH = USER_PATH + 'search/'\n+\n+\n+def _create_user(server_config):\n+    \"\"\"Create a user with a random login. Return the decoded JSON response.\"\"\"\n+    response = requests.post(\n+        server_config.base_url + USER_PATH,\n+        json={'login': type('')(randint(-999999, 999999))},\n+        **server_config.get_requests_kwargs()\n+    )\n+    response.raise_for_status()\n+    return response.json()\n+\n+\n+def _search_get(server_config, query):\n+    \"\"\"Search for users. ``query`` may be a raw query string or a dict.\"\"\"\n+    if isinstance(query, dict):\n+        query = '?' + urlencode(query)\n+    return requests.get(\n+        server_config.base_url + _SEARCH_PATH + query,\n+        **server_config.get_requests_kwargs()\n+    )\n+\n+\n+def _search_post(server_config, json):\n+    \"\"\"Search for users. ``json`` must be a JSON-encodable object.\"\"\"\n+    return requests.post(\n+        server_config.base_url + _SEARCH_PATH,\n+        json=json,\n+        **server_config.get_requests_kwargs()\n+    )\n+\n+\n+class _BaseTestCase(TestCase):\n+    \"\"\"Provides functionality common to most test cases in this module.\"\"\"\n+\n+    @classmethod\n+    def setUpClass(cls):\n+        \"\"\"Set default values for the other methods on this class.\"\"\"\n+        cls.cfg = get_config()\n+        cls.attrs_iter = ()  # ({'login': …, '_href': …}, {…})\n+        cls.responses = {}  # {'get': …, 'post': …}\n+\n+    def test_status_code(self):\n+        \"\"\"All responses should have HTTP 200 status codes.\"\"\"\n+        for action, response in self.responses.items():\n+            with self.subTest(action=action):\n+                self.assertEqual(response.status_code, 200)\n+\n+    @classmethod\n+    def tearDownClass(cls):\n+        \"\"\"Destroy all resources created in :meth:`setUpClass`.\"\"\"\n+        for attrs in cls.attrs_iter:\n+            requests.delete(\n+                cls.cfg.base_url + attrs['_href'],\n+                **cls.cfg.get_requests_kwargs()\n+            ).raise_for_status()\n+\n+\n+class MinimalTestCase(_BaseTestCase):\n+    \"\"\"Ask for all resources of a certain kind.\n+\n+    ==== ====\n+    GET  no query parameters\n+    POST ``{'criteria': {}}``\n+    ==== ====\n+\n+    \"\"\"\n+\n+    @classmethod\n+    def setUpClass(cls):\n+        \"\"\"Create one user. Execute searches.\"\"\"\n+        super(MinimalTestCase, cls).setUpClass()\n+        cls.attrs_iter = (_create_user(cls.cfg),)\n+        cls.responses = {\n+            'get': _search_get(cls.cfg, ''),\n+            'post': _search_post(cls.cfg, {'criteria': {}}),\n+        }\n+\n+    def test_user_found(self):\n+        \"\"\"All responses should include the user we created.\"\"\"\n+        for action, response in self.responses.items():\n+            with self.subTest(action=action):\n+                response.raise_for_status()\n+                self.assertIn(\n+                    self.attrs_iter[0]['login'],\n+                    {user['login'] for user in response.json()}\n+                )\n+\n+\n+class SortTestCase(_BaseTestCase):\n+    \"\"\"Ask for sorted search results.\n+\n+    ==== ====\n+    POST ``{'criteria': {'sort': [['id', 'ascending']]}}``\n+    POST ``{'criteria': {'sort': [['id', 'descending']]}}``\n+    ==== ====\n+\n+    \"\"\"\n+\n+    @classmethod\n+    def setUpClass(cls):\n+        \"\"\"Create two users. Execute searches.\"\"\"\n+        super(SortTestCase, cls).setUpClass()\n+        cls.attrs_iter = tuple((_create_user(cls.cfg) for _ in range(2)))\n+        for order in ('ascending', 'descending'):\n+            query = {'sort': [['id', order]]}\n+            cls.responses.update({\n+                # No specification exists for these GET searches.\n+                # 'get_' + order: _search_get(cls.cfg, 'unknown query'),\n+                'post_' + order: _search_post(cls.cfg, {'criteria': query}),\n+            })\n+\n+    def test_ascending(self):\n+        \"\"\"Ensure that ascending results are ordered from low to high.\"\"\"\n+        response = self.responses['post_ascending']\n+        response.raise_for_status()\n+        ids = [attrs['_id']['$oid'] for attrs in response.json()]\n+        self.assertEqual(ids, sorted(ids))\n+\n+    def test_descending(self):\n+        \"\"\"Ensure that descending results are ordered from high to low.\"\"\"\n+        response = self.responses['post_descending']\n+        response.raise_for_status()\n+        ids = [attrs['_id']['$oid'] for attrs in response.json()]\n+        self.assertEqual(ids, sorted(ids, reverse=True))\n+\n+\n+class FieldTestCase(_BaseTestCase):\n+    \"\"\"Ask for a single field in search results.\n+\n+    ==== ====\n+    GET  ``{'field': 'name'}`` (urlencoded)\n+    POST ``{'criteria': {'fields': 'name'}}``\n+    ==== ====\n+\n+    \"\"\"\n+\n+    @classmethod\n+    def setUpClass(cls):\n+        \"\"\"Create one user. Execute searches.\"\"\"\n+        super(FieldTestCase, cls).setUpClass()\n+        cls.attrs_iter = (_create_user(cls.cfg),)\n+        cls.responses = {\n+            'get': _search_get(cls.cfg, '?field=name'),\n+            'post': _search_post(cls.cfg, {'criteria': {'fields': ['name']}}),\n+        }\n+\n+    def test_field(self):\n+        \"\"\"Only the requested key should be in each response.\"\"\"\n+        for action, response in self.responses.items():\n+            with self.subTest(action=action):\n+                response.raise_for_status()\n+                for attrs in response.json():\n+                    self.assertEqual(set(attrs.keys()), {'name'})\n+\n+\n+class FieldsTestCase(_BaseTestCase):","path":"pulp_smash/tests/platform/api_v2/test_search.py","position":202,"original_position":202,"commit_id":"71d65047c3fb7e01e14491d696d5d5a1e8deda07","original_commit_id":"71d65047c3fb7e01e14491d696d5d5a1e8deda07","user":{"login":"Ichimonji10","id":1012989,"avatar_url":"https://avatars.githubusercontent.com/u/1012989?v=3","gravatar_id":"","url":"https://api.github.com/users/Ichimonji10","html_url":"https://github.com/Ichimonji10","followers_url":"https://api.github.com/users/Ichimonji10/followers","following_url":"https://api.github.com/users/Ichimonji10/following{/other_user}","gists_url":"https://api.github.com/users/Ichimonji10/gists{/gist_id}","starred_url":"https://api.github.com/users/Ichimonji10/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Ichimonji10/subscriptions","organizations_url":"https://api.github.com/users/Ichimonji10/orgs","repos_url":"https://api.github.com/users/Ichimonji10/repos","events_url":"https://api.github.com/users/Ichimonji10/events{/privacy}","received_events_url":"https://api.github.com/users/Ichimonji10/received_events","type":"User","site_admin":false},"body":"Thanks for the link to the issue at hand. That's exactly what I need!","created_at":"2015-11-09T21:15:30Z","updated_at":"2015-11-09T21:15:30Z","html_url":"https://github.com/PulpQE/pulp-smash/pull/26#discussion_r44332722","pull_request_url":"https://api.github.com/repos/PulpQE/pulp-smash/pulls/26","_links":{"self":{"href":"https://api.github.com/repos/PulpQE/pulp-smash/pulls/comments/44332722"},"html":{"href":"https://github.com/PulpQE/pulp-smash/pull/26#discussion_r44332722"},"pull_request":{"href":"https://api.github.com/repos/PulpQE/pulp-smash/pulls/26"}}},"pull_request":{"url":"https://api.github.com/repos/PulpQE/pulp-smash/pulls/26","id":49311776,"html_url":"https://github.com/PulpQE/pulp-smash/pull/26","diff_url":"https://github.com/PulpQE/pulp-smash/pull/26.diff","patch_url":"https://github.com/PulpQE/pulp-smash/pull/26.patch","issue_url":"https://api.github.com/repos/PulpQE/pulp-smash/issues/26","number":26,"state":"open","locked":false,"title":"Add tests for Pulp's searching facilities","user":{"login":"Ichimonji10","id":1012989,"avatar_url":"https://avatars.githubusercontent.com/u/1012989?v=3","gravatar_id":"","url":"https://api.github.com/users/Ichimonji10","html_url":"https://github.com/Ichimonji10","followers_url":"https://api.github.com/users/Ichimonji10/followers","following_url":"https://api.github.com/users/Ichimonji10/following{/other_user}","gists_url":"https://api.github.com/users/Ichimonji10/gists{/gist_id}","starred_url":"https://api.github.com/users/Ichimonji10/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Ichimonji10/subscriptions","organizations_url":"https://api.github.com/users/Ichimonji10/orgs","repos_url":"https://api.github.com/users/Ichimonji10/repos","events_url":"https://api.github.com/users/Ichimonji10/events{/privacy}","received_events_url":"https://api.github.com/users/Ichimonji10/received_events","type":"User","site_admin":false},"body":"Fix #19: \"Expand GET/POST search tests\"\r\n\r\nAdd a new module, `pulp_smash.tests.platform.api_v2.test_search`:\r\n\r\n> \"\"\"Test Pulp's `Searching`_ facilities.\r\n>\r\n> The tests in this module make use of the `User APIs`_. However, few\r\n> user-specific references are made. These tests could be rewritten to use\r\n> repositories or something else with only minimal changes. Thus, the name of\r\n> this module.\r\n>\r\n> Each test case executes one or more pair of semantically identical POST and GET\r\n> requests. Each pair of search results should match exactly.\r\n\r\nAll POST test cases succeed except `FieldTestCase` and `FieldsTestCase`. Note,\r\nhowever, that POST tests are doctored to achieve these results. When searching\r\nfor users, search results do not contain an \"id\" attribute. The affected tests\r\nwork around this issue by referencing `['_id']['$oid']` instead.\r\n\r\nTest results:\r\n\r\n    $ python -m unittest2 pulp_smash.tests.platform.api_v2.test_search\r\n    ..............\r\n    ======================================================================\r\n    FAIL: test_field (pulp_smash.tests.platform.api_v2.test_search.FieldTestCase) (action=u'post')\r\n    Only the requested key should be in each response.\r\n    ----------------------------------------------------------------------\r\n    Traceback (most recent call last):\r\n      File \"pulp_smash/tests/platform/api_v2/test_search.py\", line 199, in test_field\r\n        self.assertEqual(set(attrs.keys()), {'name'})\r\n    AssertionError: Items in the first set but not the second:\r\n    u'login'\r\n    u'_id'\r\n    u'_href'\r\n\r\n    ======================================================================\r\n    FAIL: test_field (pulp_smash.tests.platform.api_v2.test_search.FieldTestCase) (action=u'get')\r\n    Only the requested key should be in each response.\r\n    ----------------------------------------------------------------------\r\n    Traceback (most recent call last):\r\n      File \"pulp_smash/tests/platform/api_v2/test_search.py\", line 199, in test_field\r\n        self.assertEqual(set(attrs.keys()), {'name'})\r\n    AssertionError: Items in the first set but not the second:\r\n    u'login'\r\n    u'_id'\r\n    u'_href'\r\n\r\n    ======================================================================\r\n    FAIL: test_fields (pulp_smash.tests.platform.api_v2.test_search.FieldsTestCase) (action=u'post')\r\n    Only the requested keys should be in each response.\r\n    ----------------------------------------------------------------------\r\n    Traceback (most recent call last):\r\n      File \"pulp_smash/tests/platform/api_v2/test_search.py\", line 231, in test_fields\r\n        self.assertEqual(set(attrs.keys()), {'login', 'roles'})\r\n    AssertionError: Items in the first set but not the second:\r\n    u'_id'\r\n    u'_href'\r\n\r\n    ======================================================================\r\n    FAIL: test_fields (pulp_smash.tests.platform.api_v2.test_search.FieldsTestCase) (action=u'get')\r\n    Only the requested keys should be in each response.\r\n    ----------------------------------------------------------------------\r\n    Traceback (most recent call last):\r\n      File \"pulp_smash/tests/platform/api_v2/test_search.py\", line 231, in test_fields\r\n        self.assertEqual(set(attrs.keys()), {'login', 'roles'})\r\n    AssertionError: Items in the first set but not the second:\r\n    u'_id'\r\n    u'_href'\r\n\r\n    ----------------------------------------------------------------------\r\n    Ran 16 tests in 21.011s\r\n\r\n    FAILED (failures=4)\r\n\r\nHere's an example of one of the search results that caused the failures above:\r\n\r\n    {\r\n        '_href': '/pulp/api/v2/users/admin/',\r\n        '_id': {'$oid': '55fc38aab3df8a4f7e14987c'},\r\n        'login': 'admin',\r\n        'name': 'admin'\r\n    }","created_at":"2015-10-30T19:21:46Z","updated_at":"2015-11-09T21:15:30Z","closed_at":null,"merged_at":null,"merge_commit_sha":"623938d9b2f2fcebf6bcdaadf69105cc9d302a24","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/PulpQE/pulp-smash/pulls/26/commits","review_comments_url":"https://api.github.com/repos/PulpQE/pulp-smash/pulls/26/comments","review_comment_url":"https://api.github.com/repos/PulpQE/pulp-smash/pulls/comments{/number}","comments_url":"https://api.github.com/repos/PulpQE/pulp-smash/issues/26/comments","statuses_url":"https://api.github.com/repos/PulpQE/pulp-smash/statuses/71d65047c3fb7e01e14491d696d5d5a1e8deda07","head":{"label":"Ichimonji10:test-search","ref":"test-search","sha":"71d65047c3fb7e01e14491d696d5d5a1e8deda07","user":{"login":"Ichimonji10","id":1012989,"avatar_url":"https://avatars.githubusercontent.com/u/1012989?v=3","gravatar_id":"","url":"https://api.github.com/users/Ichimonji10","html_url":"https://github.com/Ichimonji10","followers_url":"https://api.github.com/users/Ichimonji10/followers","following_url":"https://api.github.com/users/Ichimonji10/following{/other_user}","gists_url":"https://api.github.com/users/Ichimonji10/gists{/gist_id}","starred_url":"https://api.github.com/users/Ichimonji10/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Ichimonji10/subscriptions","organizations_url":"https://api.github.com/users/Ichimonji10/orgs","repos_url":"https://api.github.com/users/Ichimonji10/repos","events_url":"https://api.github.com/users/Ichimonji10/events{/privacy}","received_events_url":"https://api.github.com/users/Ichimonji10/received_events","type":"User","site_admin":false},"repo":{"id":44113664,"name":"pulp-smash","full_name":"Ichimonji10/pulp-smash","owner":{"login":"Ichimonji10","id":1012989,"avatar_url":"https://avatars.githubusercontent.com/u/1012989?v=3","gravatar_id":"","url":"https://api.github.com/users/Ichimonji10","html_url":"https://github.com/Ichimonji10","followers_url":"https://api.github.com/users/Ichimonji10/followers","following_url":"https://api.github.com/users/Ichimonji10/following{/other_user}","gists_url":"https://api.github.com/users/Ichimonji10/gists{/gist_id}","starred_url":"https://api.github.com/users/Ichimonji10/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Ichimonji10/subscriptions","organizations_url":"https://api.github.com/users/Ichimonji10/orgs","repos_url":"https://api.github.com/users/Ichimonji10/repos","events_url":"https://api.github.com/users/Ichimonji10/events{/privacy}","received_events_url":"https://api.github.com/users/Ichimonji10/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/Ichimonji10/pulp-smash","description":"A GPL-licensed Python library that facilitates easy testing of Pulp.","fork":true,"url":"https://api.github.com/repos/Ichimonji10/pulp-smash","forks_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/forks","keys_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/teams","hooks_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/hooks","issue_events_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/issues/events{/number}","events_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/events","assignees_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/assignees{/user}","branches_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/branches{/branch}","tags_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/tags","blobs_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/git/refs{/sha}","trees_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/statuses/{sha}","languages_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/languages","stargazers_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/stargazers","contributors_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/contributors","subscribers_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/subscribers","subscription_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/subscription","commits_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/commits{/sha}","git_commits_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/git/commits{/sha}","comments_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/comments{/number}","issue_comment_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/issues/comments{/number}","contents_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/contents/{+path}","compare_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/merges","archive_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/downloads","issues_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/issues{/number}","pulls_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/pulls{/number}","milestones_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/milestones{/number}","notifications_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/labels{/name}","releases_url":"https://api.github.com/repos/Ichimonji10/pulp-smash/releases{/id}","created_at":"2015-10-12T14:46:15Z","updated_at":"2015-10-12T14:46:16Z","pushed_at":"2015-11-09T19:24:57Z","git_url":"git://github.com/Ichimonji10/pulp-smash.git","ssh_url":"git@github.com:Ichimonji10/pulp-smash.git","clone_url":"https://github.com/Ichimonji10/pulp-smash.git","svn_url":"https://github.com/Ichimonji10/pulp-smash","homepage":null,"size":199,"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":"PulpQE:master","ref":"master","sha":"b49021de77d02991e00addd723ec21f549d50a9a","user":{"login":"PulpQE","id":14839747,"avatar_url":"https://avatars.githubusercontent.com/u/14839747?v=3","gravatar_id":"","url":"https://api.github.com/users/PulpQE","html_url":"https://github.com/PulpQE","followers_url":"https://api.github.com/users/PulpQE/followers","following_url":"https://api.github.com/users/PulpQE/following{/other_user}","gists_url":"https://api.github.com/users/PulpQE/gists{/gist_id}","starred_url":"https://api.github.com/users/PulpQE/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/PulpQE/subscriptions","organizations_url":"https://api.github.com/users/PulpQE/orgs","repos_url":"https://api.github.com/users/PulpQE/repos","events_url":"https://api.github.com/users/PulpQE/events{/privacy}","received_events_url":"https://api.github.com/users/PulpQE/received_events","type":"Organization","site_admin":false},"repo":{"id":43852872,"name":"pulp-smash","full_name":"PulpQE/pulp-smash","owner":{"login":"PulpQE","id":14839747,"avatar_url":"https://avatars.githubusercontent.com/u/14839747?v=3","gravatar_id":"","url":"https://api.github.com/users/PulpQE","html_url":"https://github.com/PulpQE","followers_url":"https://api.github.com/users/PulpQE/followers","following_url":"https://api.github.com/users/PulpQE/following{/other_user}","gists_url":"https://api.github.com/users/PulpQE/gists{/gist_id}","starred_url":"https://api.github.com/users/PulpQE/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/PulpQE/subscriptions","organizations_url":"https://api.github.com/users/PulpQE/orgs","repos_url":"https://api.github.com/users/PulpQE/repos","events_url":"https://api.github.com/users/PulpQE/events{/privacy}","received_events_url":"https://api.github.com/users/PulpQE/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/PulpQE/pulp-smash","description":"A GPL-licensed Python library that facilitates easy testing of Pulp.","fork":false,"url":"https://api.github.com/repos/PulpQE/pulp-smash","forks_url":"https://api.github.com/repos/PulpQE/pulp-smash/forks","keys_url":"https://api.github.com/repos/PulpQE/pulp-smash/keys{/key_id}","collaborators_url":"https://api.github.com/repos/PulpQE/pulp-smash/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/PulpQE/pulp-smash/teams","hooks_url":"https://api.github.com/repos/PulpQE/pulp-smash/hooks","issue_events_url":"https://api.github.com/repos/PulpQE/pulp-smash/issues/events{/number}","events_url":"https://api.github.com/repos/PulpQE/pulp-smash/events","assignees_url":"https://api.github.com/repos/PulpQE/pulp-smash/assignees{/user}","branches_url":"https://api.github.com/repos/PulpQE/pulp-smash/branches{/branch}","tags_url":"https://api.github.com/repos/PulpQE/pulp-smash/tags","blobs_url":"https://api.github.com/repos/PulpQE/pulp-smash/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/PulpQE/pulp-smash/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/PulpQE/pulp-smash/git/refs{/sha}","trees_url":"https://api.github.com/repos/PulpQE/pulp-smash/git/trees{/sha}","statuses_url":"https://api.github.com/repos/PulpQE/pulp-smash/statuses/{sha}","languages_url":"https://api.github.com/repos/PulpQE/pulp-smash/languages","stargazers_url":"https://api.github.com/repos/PulpQE/pulp-smash/stargazers","contributors_url":"https://api.github.com/repos/PulpQE/pulp-smash/contributors","subscribers_url":"https://api.github.com/repos/PulpQE/pulp-smash/subscribers","subscription_url":"https://api.github.com/repos/PulpQE/pulp-smash/subscription","commits_url":"https://api.github.com/repos/PulpQE/pulp-smash/commits{/sha}","git_commits_url":"https://api.github.com/repos/PulpQE/pulp-smash/git/commits{/sha}","comments_url":"https://api.github.com/repos/PulpQE/pulp-smash/comments{/number}","issue_comment_url":"https://api.github.com/repos/PulpQE/pulp-smash/issues/comments{/number}","contents_url":"https://api.github.com/repos/PulpQE/pulp-smash/contents/{+path}","compare_url":"https://api.github.com/repos/PulpQE/pulp-smash/compare/{base}...{head}","merges_url":"https://api.github.com/repos/PulpQE/pulp-smash/merges","archive_url":"https://api.github.com/repos/PulpQE/pulp-smash/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/PulpQE/pulp-smash/downloads","issues_url":"https://api.github.com/repos/PulpQE/pulp-smash/issues{/number}","pulls_url":"https://api.github.com/repos/PulpQE/pulp-smash/pulls{/number}","milestones_url":"https://api.github.com/repos/PulpQE/pulp-smash/milestones{/number}","notifications_url":"https://api.github.com/repos/PulpQE/pulp-smash/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/PulpQE/pulp-smash/labels{/name}","releases_url":"https://api.github.com/repos/PulpQE/pulp-smash/releases{/id}","created_at":"2015-10-08T00:35:48Z","updated_at":"2015-10-08T15:29:22Z","pushed_at":"2015-11-09T19:24:58Z","git_url":"git://github.com/PulpQE/pulp-smash.git","ssh_url":"git@github.com:PulpQE/pulp-smash.git","clone_url":"https://github.com/PulpQE/pulp-smash.git","svn_url":"https://github.com/PulpQE/pulp-smash","homepage":null,"size":415,"stargazers_count":1,"watchers_count":1,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":7,"mirror_url":null,"open_issues_count":22,"forks":7,"open_issues":22,"watchers":1,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/PulpQE/pulp-smash/pulls/26"},"html":{"href":"https://github.com/PulpQE/pulp-smash/pull/26"},"issue":{"href":"https://api.github.com/repos/PulpQE/pulp-smash/issues/26"},"comments":{"href":"https://api.github.com/repos/PulpQE/pulp-smash/issues/26/comments"},"review_comments":{"href":"https://api.github.com/repos/PulpQE/pulp-smash/pulls/26/comments"},"review_comment":{"href":"https://api.github.com/repos/PulpQE/pulp-smash/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/PulpQE/pulp-smash/pulls/26/commits"},"statuses":{"href":"https://api.github.com/repos/PulpQE/pulp-smash/statuses/71d65047c3fb7e01e14491d696d5d5a1e8deda07"}}}}