From a433a2fe3dd4dc6d7a72849f27dac5a541362fee Mon Sep 17 00:00:00 2001 From: Justin Kufro Date: Tue, 4 Dec 2018 20:54:31 -0500 Subject: [PATCH] Traffic Endpoints Support (#977) Added support for the traffic endpoints found at https://developer.github.com/v3/repos/traffic/. We added four functions to the Repository class (one for each of the endpoints) with corresponding unit tests. Fixes #926 --- doc/examples/Repository.rst | 98 +++++++++++++++++++ github/Clones.py | 77 +++++++++++++++ github/Path.py | 88 +++++++++++++++++ github/Referrer.py | 77 +++++++++++++++ github/Repository.py | 93 +++++++++++++++++- github/View.py | 77 +++++++++++++++ github/tests/AllTests.py | 1 + github/tests/ReplayData/Repository.setUp.txt | 1 - github/tests/ReplayData/Traffic.setUp.txt | 22 +++++ .../ReplayData/Traffic.testGetClones.txt | 11 +++ .../tests/ReplayData/Traffic.testGetPaths.txt | 11 +++ .../ReplayData/Traffic.testGetReferrers.txt | 11 +++ .../tests/ReplayData/Traffic.testGetViews.txt | 11 +++ github/tests/Traffic.py | 73 ++++++++++++++ 14 files changed, 646 insertions(+), 5 deletions(-) create mode 100644 github/Clones.py create mode 100644 github/Path.py create mode 100644 github/Referrer.py create mode 100644 github/View.py create mode 100644 github/tests/ReplayData/Traffic.setUp.txt create mode 100644 github/tests/ReplayData/Traffic.testGetClones.txt create mode 100644 github/tests/ReplayData/Traffic.testGetPaths.txt create mode 100644 github/tests/ReplayData/Traffic.testGetReferrers.txt create mode 100644 github/tests/ReplayData/Traffic.testGetViews.txt create mode 100644 github/tests/Traffic.py diff --git a/doc/examples/Repository.rst b/doc/examples/Repository.rst index bfc3b4fa..22205ae1 100644 --- a/doc/examples/Repository.rst +++ b/doc/examples/Repository.rst @@ -138,6 +138,104 @@ Delete a file in the repository >>> repo.delete_file(contents.path, "remove test", contents.sha, branch="test") {'commit': Commit(sha="0f40b0b4f31f62454f1758d7e6b384795e48fd96"), 'content': NotSet} +Get the top 10 referrers over the last 14 days +------------------------------- + +.. code-block:: python + + >>> repo = g.get_repo("PyGithub/PyGithub") + >>> contents = repo.get_top_referrers() + >>> print(contents) + [ + Referrer(referrer="Google", count=4, uniques=3), + Referrer(referrer="stackoverflow.com", count=2, uniques=2), + Referrer(referrer="eggsonbread.com", count=1, uniques=1), + Referrer(referrer="yandex.ru", count=1, uniques=1) + ] + +Get the top 10 popular contents over the last 14 days +------------------------------- + +.. code-block:: python + + >>> repo = g.get_repo("PyGithub/PyGithub") + >>> contents = repo.get_top_paths() + >>> print(contents) + [ + Path(path="/github/hubot", title="github/hubot: A customizable life embetterment robot.", count=3542, uniques=2225), + Path(path="/github/hubot/blob/master/docs/scripting.md", title="hubot/scripting.md at master · github/hubot · GitHub", count=1707, uniques=804), + Path(path="/github/hubot/tree/master/docs", title="hubot/docs at master · github/hubot · GitHub", count=685, uniques=435), + Path(path="/github/hubot/tree/master/src", title="hubot/src at master · github/hubot · GitHub", count=577, uniques=347), + Path(path="/github/hubot/blob/master/docs/index.md", title="hubot/index.md at master · github/hubot · GitHub", count=379, uniques=259), + Path(path="/github/hubot/blob/master/docs/adapters.md", title="hubot/adapters.md at master · github/hubot · GitHub", count=354, uniques=201), + Path(path="/github/hubot/tree/master/examples", title="hubot/examples at master · github/hubot · GitHub", count=340, uniques=260), + Path(path="/github/hubot/blob/master/docs/deploying/heroku.md", title="hubot/heroku.md at master · github/hubot · GitHub", count=324, uniques=217), + Path(path="/github/hubot/blob/master/src/robot.coffee", title="hubot/robot.coffee at master · github/hubot · GitHub", count=293, uniques=191), + Path(path="/github/hubot/blob/master/LICENSE.md", title="hubot/LICENSE.md at master · github/hubot · GitHub", count=281, uniques=222) + ] + +Get number of clones and breakdown for the last 14 days +------------------------------- + +.. code-block:: python + + >>> repo = g.get_repo("PyGithub/PyGithub") + >>> contents = repo.get_clones_traffic() + >>> contents = repo.get_clones_traffic(per="week") + >>> print(contents) + { + "count": 173, + "uniques": 128, + "clones": [ + Clones(timestamp=2016-10-10 00:00:00, count=2, uniques=1), + Clones(timestamp=2016-10-11 00:00:00, count=17, uniques=16), + Clones(timestamp=2016-10-12 00:00:00, count=21, uniques=15), + Clones(timestamp=2016-10-13 00:00:00, count=8, uniques=7), + Clones(timestamp=2016-10-14 00:00:00, count=5, uniques=5), + Clones(timestamp=2016-10-15 00:00:00, count=2, uniques=2), + Clones(timestamp=2016-10-16 00:00:00, count=8, uniques=7), + Clones(timestamp=2016-10-17 00:00:00, count=26, uniques=15), + Clones(timestamp=2016-10-18 00:00:00, count=19, uniques=17), + Clones(timestamp=2016-10-19 00:00:00, count=19, uniques=14), + Clones(timestamp=2016-10-20 00:00:00, count=19, uniques=15), + Clones(timestamp=2016-10-21 00:00:00, count=9, uniques=7), + Clones(timestamp=2016-10-22 00:00:00, count=5, uniques=5), + Clones(timestamp=2016-10-23 00:00:00, count=6, uniques=5), + Clones(timestamp=2016-10-24 00:00:00, count=7, uniques=5) + ] + } + +Get number of views and breakdown for the last 14 days +------------------------------- + +.. code-block:: python + + >>> repo = g.get_repo("PyGithub/PyGithub") + >>> contents = repo.get_views_traffic() + >>> contents = repo.get_views_traffic(per="week") + >>> print(contents) + { + "count": 14850, + "uniques": 3782, + "views": [ + View(timestamp=2016-10-10 00:00:00, count=440, uniques=143), + View(timestamp=2016-10-11 00:00:00, count=1308, uniques=414), + View(timestamp=2016-10-12 00:00:00, count=1486, uniques=452), + View(timestamp=2016-10-13 00:00:00, count=1170, uniques=401), + View(timestamp=2016-10-14 00:00:00, count=868, uniques=266), + View(timestamp=2016-10-15 00:00:00, count=495, uniques=157), + View(timestamp=2016-10-16 00:00:00, count=524, uniques=175), + View(timestamp=2016-10-17 00:00:00, count=1263, uniques=412), + View(timestamp=2016-10-18 00:00:00, count=1402, uniques=417), + View(timestamp=2016-10-19 00:00:00, count=1394, uniques=424), + View(timestamp=2016-10-20 00:00:00, count=1492, uniques=448), + View(timestamp=2016-10-21 00:00:00, count=1153, uniques=332), + View(timestamp=2016-10-22 00:00:00, count=566, uniques=168), + View(timestamp=2016-10-23 00:00:00, count=675, uniques=184), + View(timestamp=2016-10-24 00:00:00, count=614, uniques=237) + ] + } + ======= ====== Mark the notifications of the repository as read diff --git a/github/Clones.py b/github/Clones.py new file mode 100644 index 00000000..b8c1adc7 --- /dev/null +++ b/github/Clones.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- + +############################ Copyrights and license ############################ +# # +# Copyright 2018 Justin Kufro # +# Copyright 2018 Ivan Minno # +# Copyright 2018 Zilei Gu # +# Copyright 2018 Yves Zumbach # +# Copyright 2018 Leying Chen # +# # +# This file is part of PyGithub. # +# http://pygithub.readthedocs.io/ # +# # +# PyGithub is free software: you can redistribute it and/or modify it under # +# the terms of the GNU Lesser General Public License as published by the Free # +# Software Foundation, either version 3 of the License, or (at your option) # +# any later version. # +# # +# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY # +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # +# details. # +# # +# You should have received a copy of the GNU Lesser General Public License # +# along with PyGithub. If not, see . # +# # +################################################################################ + +import github.GithubObject + + +class Clones(github.GithubObject.NonCompletableGithubObject): + """ + This class represents a popular Path for a GitHub repository. + The reference can be found here https://developer.github.com/v3/repos/traffic/ + """ + + def __repr__(self): + return self.get__repr__({ + "timestamp": self._timestamp.value, + "count": self._count.value, + "uniques": self._uniques.value + }) + + @property + def timestamp(self): + """ + :type: datetime.datetime + """ + return self._timestamp.value + + @property + def count(self): + """ + :type: integer + """ + return self._count.value + + @property + def uniques(self): + """ + :type: integer + """ + return self._uniques.value + + def _initAttributes(self): + self._timestamp = github.GithubObject.NotSet + self._count = github.GithubObject.NotSet + self._uniques = github.GithubObject.NotSet + + def _useAttributes(self, attributes): + if "timestamp" in attributes: # pragma no branch + self._timestamp = self._makeDatetimeAttribute(attributes["timestamp"]) + if "count" in attributes: # pragma no branch + self._count = self._makeIntAttribute(attributes["count"]) + if "uniques" in attributes: # pragma no branch + self._uniques = self._makeIntAttribute(attributes["uniques"]) diff --git a/github/Path.py b/github/Path.py new file mode 100644 index 00000000..615c0da1 --- /dev/null +++ b/github/Path.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- + +############################ Copyrights and license ############################ +# # +# Copyright 2018 Justin Kufro # +# Copyright 2018 Ivan Minno # +# Copyright 2018 Zilei Gu # +# Copyright 2018 Yves Zumbach # +# Copyright 2018 Leying Chen # +# # +# This file is part of PyGithub. # +# http://pygithub.readthedocs.io/ # +# # +# PyGithub is free software: you can redistribute it and/or modify it under # +# the terms of the GNU Lesser General Public License as published by the Free # +# Software Foundation, either version 3 of the License, or (at your option) # +# any later version. # +# # +# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY # +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # +# details. # +# # +# You should have received a copy of the GNU Lesser General Public License # +# along with PyGithub. If not, see . # +# # +################################################################################ + +import github.GithubObject + + +class Path(github.GithubObject.NonCompletableGithubObject): + """ + This class represents a popular Path for a GitHub repository. + The reference can be found here https://developer.github.com/v3/repos/traffic/ + """ + + def __repr__(self): + return self.get__repr__({ + "path": self._path.value, + "title": self._title.value, + "count": self._count.value, + "uniques": self._uniques.value + }) + + @property + def path(self): + """ + :type: string + """ + return self._path.value + + @property + def title(self): + """ + :type: string + """ + return self._title.value + + @property + def count(self): + """ + :type: integer + """ + return self._count.value + + @property + def uniques(self): + """ + :type: integer + """ + return self._uniques.value + + def _initAttributes(self): + self._path = github.GithubObject.NotSet + self._title = github.GithubObject.NotSet + self._count = github.GithubObject.NotSet + self._uniques = github.GithubObject.NotSet + + def _useAttributes(self, attributes): + if "path" in attributes: # pragma no branch + self._path = self._makeStringAttribute(attributes["path"]) + if "title" in attributes: # pragma no branch + self._title = self._makeStringAttribute(attributes["title"]) + if "count" in attributes: # pragma no branch + self._count = self._makeIntAttribute(attributes["count"]) + if "uniques" in attributes: # pragma no branch + self._uniques = self._makeIntAttribute(attributes["uniques"]) diff --git a/github/Referrer.py b/github/Referrer.py new file mode 100644 index 00000000..eb14931b --- /dev/null +++ b/github/Referrer.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- + +############################ Copyrights and license ############################ +# # +# Copyright 2018 Justin Kufro # +# Copyright 2018 Ivan Minno # +# Copyright 2018 Zilei Gu # +# Copyright 2018 Yves Zumbach # +# Copyright 2018 Leying Chen # +# # +# This file is part of PyGithub. # +# http://pygithub.readthedocs.io/ # +# # +# PyGithub is free software: you can redistribute it and/or modify it under # +# the terms of the GNU Lesser General Public License as published by the Free # +# Software Foundation, either version 3 of the License, or (at your option) # +# any later version. # +# # +# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY # +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # +# details. # +# # +# You should have received a copy of the GNU Lesser General Public License # +# along with PyGithub. If not, see . # +# # +################################################################################ + +import github.GithubObject + + +class Referrer(github.GithubObject.NonCompletableGithubObject): + """ + This class represents a popylar Referrer for a GitHub repository. + The reference can be found here https://developer.github.com/v3/repos/traffic/ + """ + + def __repr__(self): + return self.get__repr__({ + "referrer": self._referrer.value, + "count": self._count.value, + "uniques": self._uniques.value + }) + + @property + def referrer(self): + """ + :type: string + """ + return self._referrer.value + + @property + def count(self): + """ + :type: integer + """ + return self._count.value + + @property + def uniques(self): + """ + :type: integer + """ + return self._uniques.value + + def _initAttributes(self): + self._referrer = github.GithubObject.NotSet + self._count = github.GithubObject.NotSet + self._uniques = github.GithubObject.NotSet + + def _useAttributes(self, attributes): + if "referrer" in attributes: # pragma no branch + self._referrer = self._makeStringAttribute(attributes["referrer"]) + if "count" in attributes: # pragma no branch + self._count = self._makeIntAttribute(attributes["count"]) + if "uniques" in attributes: # pragma no branch + self._uniques = self._makeIntAttribute(attributes["uniques"]) diff --git a/github/Repository.py b/github/Repository.py index e369b690..ef7b1dd2 100644 --- a/github/Repository.py +++ b/github/Repository.py @@ -60,7 +60,12 @@ # Copyright 2018 per1234 # # Copyright 2018 sechastain # # Copyright 2018 sfdye # -# Copyright 2018 Vinay Hegde +# Copyright 2018 Vinay Hegde # +# Copyright 2018 Justin Kufro # +# Copyright 2018 Ivan Minno # +# Copyright 2018 Zilei Gu # +# Copyright 2018 Yves Zumbach # +# Copyright 2018 Leying Chen # # # # This file is part of PyGithub. # # http://pygithub.readthedocs.io/ # @@ -124,6 +129,10 @@ import github.StatsCodeFrequency import github.StatsParticipation import github.StatsPunchCard import github.Stargazer +import github.Referrer +import github.Path +import github.Clones +import github.View import Consts @@ -1470,17 +1479,93 @@ class Repository(github.GithubObject.CompletableGithubObject): ] return github.ContentFile.ContentFile(self._requester, headers, data, completed=True) + def get_top_referrers(self): + """ + :calls: `GET /repos/:owner/:repo/traffic/popular/referrers `_ + :rtype: :class:`list` of :class:`github.Referrer.Referrer` + """ + url_parameters = dict() + headers, data = self._requester.requestJsonAndCheck( + "GET", + self.url + "/traffic/popular/referrers" + ) + if isinstance(data, list): + return [ + github.Referrer.Referrer(self._requester, headers, item, completed=True) + for item in data + ] + + def get_top_paths(self): + """ + :calls: `GET /repos/:owner/:repo/traffic/popular/paths `_ + :rtype: :class:`list` of :class:`github.Path.Path` + """ + url_parameters = dict() + headers, data = self._requester.requestJsonAndCheck( + "GET", + self.url + "/traffic/popular/paths" + ) + if isinstance(data, list): + return [ + github.Path.Path(self._requester, headers, item, completed=True) + for item in data + ] + + def get_views_traffic(self, per=github.GithubObject.NotSet): + """ + :calls: `GET /repos/:owner/:repo/traffic/views `_ + :param per: string, must be one of day or week, day by default + :rtype: None or list of :class:`github.View.View` + """ + assert per is github.GithubObject.NotSet or (isinstance(per, (str, unicode)) and (per == "day" or per == "week")), "per must be day or week, day by default" + url_parameters = dict() + if per is not github.GithubObject.NotSet: + url_parameters["per"] = per + headers, data = self._requester.requestJsonAndCheck( + "GET", + self.url + "/traffic/views", + parameters=url_parameters + ) + if (isinstance(data, dict)) and ("views" in data) and (isinstance(data["views"], list)): + data["views"] = [ + github.View.View(self._requester, headers, item, completed=True) + for item in data["views"] + ] + return data + + def get_clones_traffic(self, per=github.GithubObject.NotSet): + """ + :calls: `GET /repos/:owner/:repo/traffic/clones `_ + :param per: string, must be one of day or week, day by default + :rtype: None or list of :class:`github.Clone.Clone` + """ + assert per is github.GithubObject.NotSet or (isinstance(per, (str, unicode)) and (per == "day" or per == "week")), "per must be day or week, day by default" + url_parameters = dict() + if per is not github.GithubObject.NotSet: + url_parameters["per"] = per + headers, data = self._requester.requestJsonAndCheck( + "GET", + self.url + "/traffic/clones", + parameters=url_parameters + ) + if (isinstance(data, dict)) and ("clones" in data) and (isinstance(data["clones"], list)): + data["clones"] = [ + github.Clones.Clones(self._requester, headers, item, completed=True) + for item in data["clones"] + ] + return data + def get_projects(self, state=github.GithubObject.NotSet): """ :calls: `GET /repos/:owner/:repo/projects `_ :rtype: :class:`github.PaginatedList.PaginatedList` of :class:`github.Project.Project` :param state: string """ - + url_parameters = dict() if state is not github.GithubObject.NotSet: url_parameters["state"] = state - + return github.PaginatedList.PaginatedList( github.Project.Project, self._requester, @@ -2839,7 +2924,7 @@ class Repository(github.GithubObject.CompletableGithubObject): self._teams_url = self._makeStringAttribute(attributes["teams_url"]) if "trees_url" in attributes: # pragma no branch self._trees_url = self._makeStringAttribute(attributes["trees_url"]) - if "topics" in attributes: # pragma no branch + if "topics" in attributes: # pragma no branch self._topics = self._makeListOfStringsAttribute(attributes["topics"]) if "updated_at" in attributes: # pragma no branch self._updated_at = self._makeDatetimeAttribute(attributes["updated_at"]) diff --git a/github/View.py b/github/View.py new file mode 100644 index 00000000..ed0bce5d --- /dev/null +++ b/github/View.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- + +############################ Copyrights and license ############################ +# # +# Copyright 2018 Justin Kufro # +# Copyright 2018 Ivan Minno # +# Copyright 2018 Zilei Gu # +# Copyright 2018 Yves Zumbach # +# Copyright 2018 Leying Chen # +# # +# This file is part of PyGithub. # +# http://pygithub.readthedocs.io/ # +# # +# PyGithub is free software: you can redistribute it and/or modify it under # +# the terms of the GNU Lesser General Public License as published by the Free # +# Software Foundation, either version 3 of the License, or (at your option) # +# any later version. # +# # +# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY # +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # +# details. # +# # +# You should have received a copy of the GNU Lesser General Public License # +# along with PyGithub. If not, see . # +# # +################################################################################ + +import github.GithubObject + + +class View(github.GithubObject.NonCompletableGithubObject): + """ + This class represents a popular Path for a GitHub repository. + The reference can be found here https://developer.github.com/v3/repos/traffic/ + """ + + def __repr__(self): + return self.get__repr__({ + "timestamp": self._timestamp.value, + "count": self._count.value, + "uniques": self._uniques.value + }) + + @property + def timestamp(self): + """ + :type: datetime.datetime + """ + return self._timestamp.value + + @property + def count(self): + """ + :type: integer + """ + return self._count.value + + @property + def uniques(self): + """ + :type: integer + """ + return self._uniques.value + + def _initAttributes(self): + self._timestamp = github.GithubObject.NotSet + self._count = github.GithubObject.NotSet + self._uniques = github.GithubObject.NotSet + + def _useAttributes(self, attributes): + if "timestamp" in attributes: # pragma no branch + self._timestamp = self._makeDatetimeAttribute(attributes["timestamp"]) + if "count" in attributes: # pragma no branch + self._count = self._makeIntAttribute(attributes["count"]) + if "uniques" in attributes: # pragma no branch + self._uniques = self._makeIntAttribute(attributes["uniques"]) diff --git a/github/tests/AllTests.py b/github/tests/AllTests.py index ba787fca..4f2001b1 100644 --- a/github/tests/AllTests.py +++ b/github/tests/AllTests.py @@ -89,6 +89,7 @@ from SourceImport import * from Status import * from Tag import * from Team import * +from Traffic import * from UserKey import * from PaginatedList import * diff --git a/github/tests/ReplayData/Repository.setUp.txt b/github/tests/ReplayData/Repository.setUp.txt index 97249152..70a38eaa 100644 --- a/github/tests/ReplayData/Repository.setUp.txt +++ b/github/tests/ReplayData/Repository.setUp.txt @@ -19,4 +19,3 @@ None 200 [('status', '200 OK'), ('x-ratelimit-remaining', '4911'), ('content-length', '1129'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"1a93ec821b0bd7094340a9fc34017aa0"'), ('date', 'Sun, 27 May 2012 07:17:09 GMT'), ('content-type', 'application/json; charset=utf-8')] {"clone_url":"https://github.com/jacquev6/PyGithub.git","has_downloads":true,"watchers":15,"git_url":"git://github.com/jacquev6/PyGithub.git","updated_at":"2012-05-27T06:55:28Z","permissions":{"pull":true,"admin":true,"push":true},"homepage":"http://vincent-jacques.net/PyGithub","url":"https://api.github.com/repos/jacquev6/PyGithub","mirror_url":null,"has_wiki":false,"has_issues":true,"fork":false,"forks":3,"size":308,"private":false,"open_issues":16,"svn_url":"https://github.com/jacquev6/PyGithub","owner":{"url":"https://api.github.com/users/jacquev6","avatar_url":"https://secure.gravatar.com/avatar/b68de5ae38616c296fa345d2b9df2225?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png","gravatar_id":"b68de5ae38616c296fa345d2b9df2225","login":"jacquev6","id":327146},"name":"PyGithub","language":"Python","description":"Python library implementing the full Github API v3","ssh_url":"git@github.com:jacquev6/PyGithub.git","pushed_at":"2012-05-27T06:00:28Z","created_at":"2012-02-25T12:53:47Z","id":3544490,"html_url":"https://github.com/jacquev6/PyGithub","full_name":"jacquev6/PyGithub"} - diff --git a/github/tests/ReplayData/Traffic.setUp.txt b/github/tests/ReplayData/Traffic.setUp.txt new file mode 100644 index 00000000..e0c04edb --- /dev/null +++ b/github/tests/ReplayData/Traffic.setUp.txt @@ -0,0 +1,22 @@ +https +GET +api.github.com +None +/user +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Sun, 02 Dec 2018 18:37:43 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4996'), ('X-RateLimit-Reset', '1543779296'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP'), ('ETag', 'W/"b4c424454d0be9377d38527af8f2c87b"'), ('Last-Modified', 'Mon, 19 Nov 2018 17:29:23 GMT'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'F7B6:56B4:121702B:263CA83:5C042677')] +{"login":"jkufro","id":24628687,"node_id":"MDQ6VXNlcjI0NjI4Njg3","avatar_url":"https://avatars2.githubusercontent.com/u/24628687?v=4","gravatar_id":"","url":"https://api.github.com/users/jkufro","html_url":"https://github.com/jkufro","followers_url":"https://api.github.com/users/jkufro/followers","following_url":"https://api.github.com/users/jkufro/following{/other_user}","gists_url":"https://api.github.com/users/jkufro/gists{/gist_id}","starred_url":"https://api.github.com/users/jkufro/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jkufro/subscriptions","organizations_url":"https://api.github.com/users/jkufro/orgs","repos_url":"https://api.github.com/users/jkufro/repos","events_url":"https://api.github.com/users/jkufro/events{/privacy}","received_events_url":"https://api.github.com/users/jkufro/received_events","type":"User","site_admin":false,"name":"Justin Kufro","company":null,"blog":"justinkufro.com","location":null,"email":null,"hireable":null,"bio":"I'm an Information Systems student at Carnegie Mellon University","public_repos":7,"public_gists":0,"followers":0,"following":0,"created_at":"2016-12-18T00:04:35Z","updated_at":"2018-11-19T17:29:23Z","private_gists":0,"total_private_repos":5,"owned_private_repos":5,"disk_usage":3674,"collaborators":2,"two_factor_authentication":false,"plan":{"name":"developer","space":976562499,"collaborators":0,"private_repos":9999}} + +https +GET +api.github.com +None +/repos/jkufro/PyGithub +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Sun, 02 Dec 2018 18:37:43 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4995'), ('X-RateLimit-Reset', '1543779296'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP'), ('ETag', 'W/"f9e6d36183888f8f7004d148eb3ac044"'), ('Last-Modified', 'Tue, 27 Nov 2018 19:00:14 GMT'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'F7B7:56B4:1217044:263CACA:5C042677')] +{"id":159384744,"node_id":"MDEwOlJlcG9zaXRvcnkxNTkzODQ3NDQ=","name":"PyGithub","full_name":"jkufro/PyGithub","private":false,"owner":{"login":"jkufro","id":24628687,"node_id":"MDQ6VXNlcjI0NjI4Njg3","avatar_url":"https://avatars2.githubusercontent.com/u/24628687?v=4","gravatar_id":"","url":"https://api.github.com/users/jkufro","html_url":"https://github.com/jkufro","followers_url":"https://api.github.com/users/jkufro/followers","following_url":"https://api.github.com/users/jkufro/following{/other_user}","gists_url":"https://api.github.com/users/jkufro/gists{/gist_id}","starred_url":"https://api.github.com/users/jkufro/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jkufro/subscriptions","organizations_url":"https://api.github.com/users/jkufro/orgs","repos_url":"https://api.github.com/users/jkufro/repos","events_url":"https://api.github.com/users/jkufro/events{/privacy}","received_events_url":"https://api.github.com/users/jkufro/received_events","type":"User","site_admin":false},"html_url":"https://github.com/jkufro/PyGithub","description":"Typed interactions with the GitHub API v3","fork":true,"url":"https://api.github.com/repos/jkufro/PyGithub","forks_url":"https://api.github.com/repos/jkufro/PyGithub/forks","keys_url":"https://api.github.com/repos/jkufro/PyGithub/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jkufro/PyGithub/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jkufro/PyGithub/teams","hooks_url":"https://api.github.com/repos/jkufro/PyGithub/hooks","issue_events_url":"https://api.github.com/repos/jkufro/PyGithub/issues/events{/number}","events_url":"https://api.github.com/repos/jkufro/PyGithub/events","assignees_url":"https://api.github.com/repos/jkufro/PyGithub/assignees{/user}","branches_url":"https://api.github.com/repos/jkufro/PyGithub/branches{/branch}","tags_url":"https://api.github.com/repos/jkufro/PyGithub/tags","blobs_url":"https://api.github.com/repos/jkufro/PyGithub/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jkufro/PyGithub/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jkufro/PyGithub/git/refs{/sha}","trees_url":"https://api.github.com/repos/jkufro/PyGithub/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jkufro/PyGithub/statuses/{sha}","languages_url":"https://api.github.com/repos/jkufro/PyGithub/languages","stargazers_url":"https://api.github.com/repos/jkufro/PyGithub/stargazers","contributors_url":"https://api.github.com/repos/jkufro/PyGithub/contributors","subscribers_url":"https://api.github.com/repos/jkufro/PyGithub/subscribers","subscription_url":"https://api.github.com/repos/jkufro/PyGithub/subscription","commits_url":"https://api.github.com/repos/jkufro/PyGithub/commits{/sha}","git_commits_url":"https://api.github.com/repos/jkufro/PyGithub/git/commits{/sha}","comments_url":"https://api.github.com/repos/jkufro/PyGithub/comments{/number}","issue_comment_url":"https://api.github.com/repos/jkufro/PyGithub/issues/comments{/number}","contents_url":"https://api.github.com/repos/jkufro/PyGithub/contents/{+path}","compare_url":"https://api.github.com/repos/jkufro/PyGithub/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jkufro/PyGithub/merges","archive_url":"https://api.github.com/repos/jkufro/PyGithub/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jkufro/PyGithub/downloads","issues_url":"https://api.github.com/repos/jkufro/PyGithub/issues{/number}","pulls_url":"https://api.github.com/repos/jkufro/PyGithub/pulls{/number}","milestones_url":"https://api.github.com/repos/jkufro/PyGithub/milestones{/number}","notifications_url":"https://api.github.com/repos/jkufro/PyGithub/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jkufro/PyGithub/labels{/name}","releases_url":"https://api.github.com/repos/jkufro/PyGithub/releases{/id}","deployments_url":"https://api.github.com/repos/jkufro/PyGithub/deployments","created_at":"2018-11-27T19:00:09Z","updated_at":"2018-11-27T19:00:14Z","pushed_at":"2018-12-02T17:41:01Z","git_url":"git://github.com/jkufro/PyGithub.git","ssh_url":"git@github.com:jkufro/PyGithub.git","clone_url":"https://github.com/jkufro/PyGithub.git","svn_url":"https://github.com/jkufro/PyGithub","homepage":"https://pygithub.readthedocs.io/","size":11767,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"lgpl-3.0","name":"GNU Lesser General Public License v3.0","spdx_id":"LGPL-3.0","url":"https://api.github.com/licenses/lgpl-3.0","node_id":"MDc6TGljZW5zZTEy"},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master","permissions":{"admin":true,"push":true,"pull":true},"allow_squash_merge":true,"allow_merge_commit":true,"allow_rebase_merge":true,"parent":{"id":3544490,"node_id":"MDEwOlJlcG9zaXRvcnkzNTQ0NDkw","name":"PyGithub","full_name":"PyGithub/PyGithub","private":false,"owner":{"login":"PyGithub","id":11288996,"node_id":"MDEyOk9yZ2FuaXphdGlvbjExMjg4OTk2","avatar_url":"https://avatars0.githubusercontent.com/u/11288996?v=4","gravatar_id":"","url":"https://api.github.com/users/PyGithub","html_url":"https://github.com/PyGithub","followers_url":"https://api.github.com/users/PyGithub/followers","following_url":"https://api.github.com/users/PyGithub/following{/other_user}","gists_url":"https://api.github.com/users/PyGithub/gists{/gist_id}","starred_url":"https://api.github.com/users/PyGithub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/PyGithub/subscriptions","organizations_url":"https://api.github.com/users/PyGithub/orgs","repos_url":"https://api.github.com/users/PyGithub/repos","events_url":"https://api.github.com/users/PyGithub/events{/privacy}","received_events_url":"https://api.github.com/users/PyGithub/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/PyGithub/PyGithub","description":"Typed interactions with the GitHub API v3","fork":false,"url":"https://api.github.com/repos/PyGithub/PyGithub","forks_url":"https://api.github.com/repos/PyGithub/PyGithub/forks","keys_url":"https://api.github.com/repos/PyGithub/PyGithub/keys{/key_id}","collaborators_url":"https://api.github.com/repos/PyGithub/PyGithub/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/PyGithub/PyGithub/teams","hooks_url":"https://api.github.com/repos/PyGithub/PyGithub/hooks","issue_events_url":"https://api.github.com/repos/PyGithub/PyGithub/issues/events{/number}","events_url":"https://api.github.com/repos/PyGithub/PyGithub/events","assignees_url":"https://api.github.com/repos/PyGithub/PyGithub/assignees{/user}","branches_url":"https://api.github.com/repos/PyGithub/PyGithub/branches{/branch}","tags_url":"https://api.github.com/repos/PyGithub/PyGithub/tags","blobs_url":"https://api.github.com/repos/PyGithub/PyGithub/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/PyGithub/PyGithub/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/PyGithub/PyGithub/git/refs{/sha}","trees_url":"https://api.github.com/repos/PyGithub/PyGithub/git/trees{/sha}","statuses_url":"https://api.github.com/repos/PyGithub/PyGithub/statuses/{sha}","languages_url":"https://api.github.com/repos/PyGithub/PyGithub/languages","stargazers_url":"https://api.github.com/repos/PyGithub/PyGithub/stargazers","contributors_url":"https://api.github.com/repos/PyGithub/PyGithub/contributors","subscribers_url":"https://api.github.com/repos/PyGithub/PyGithub/subscribers","subscription_url":"https://api.github.com/repos/PyGithub/PyGithub/subscription","commits_url":"https://api.github.com/repos/PyGithub/PyGithub/commits{/sha}","git_commits_url":"https://api.github.com/repos/PyGithub/PyGithub/git/commits{/sha}","comments_url":"https://api.github.com/repos/PyGithub/PyGithub/comments{/number}","issue_comment_url":"https://api.github.com/repos/PyGithub/PyGithub/issues/comments{/number}","contents_url":"https://api.github.com/repos/PyGithub/PyGithub/contents/{+path}","compare_url":"https://api.github.com/repos/PyGithub/PyGithub/compare/{base}...{head}","merges_url":"https://api.github.com/repos/PyGithub/PyGithub/merges","archive_url":"https://api.github.com/repos/PyGithub/PyGithub/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/PyGithub/PyGithub/downloads","issues_url":"https://api.github.com/repos/PyGithub/PyGithub/issues{/number}","pulls_url":"https://api.github.com/repos/PyGithub/PyGithub/pulls{/number}","milestones_url":"https://api.github.com/repos/PyGithub/PyGithub/milestones{/number}","notifications_url":"https://api.github.com/repos/PyGithub/PyGithub/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/PyGithub/PyGithub/labels{/name}","releases_url":"https://api.github.com/repos/PyGithub/PyGithub/releases{/id}","deployments_url":"https://api.github.com/repos/PyGithub/PyGithub/deployments","created_at":"2012-02-25T12:53:47Z","updated_at":"2018-12-01T07:01:06Z","pushed_at":"2018-12-02T11:35:58Z","git_url":"git://github.com/PyGithub/PyGithub.git","ssh_url":"git@github.com:PyGithub/PyGithub.git","clone_url":"https://github.com/PyGithub/PyGithub.git","svn_url":"https://github.com/PyGithub/PyGithub","homepage":"https://pygithub.readthedocs.io/","size":11536,"stargazers_count":2232,"watchers_count":2232,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":757,"mirror_url":null,"archived":false,"open_issues_count":57,"license":{"key":"lgpl-3.0","name":"GNU Lesser General Public License v3.0","spdx_id":"LGPL-3.0","url":"https://api.github.com/licenses/lgpl-3.0","node_id":"MDc6TGljZW5zZTEy"},"forks":757,"open_issues":57,"watchers":2232,"default_branch":"master"},"source":{"id":3544490,"node_id":"MDEwOlJlcG9zaXRvcnkzNTQ0NDkw","name":"PyGithub","full_name":"PyGithub/PyGithub","private":false,"owner":{"login":"PyGithub","id":11288996,"node_id":"MDEyOk9yZ2FuaXphdGlvbjExMjg4OTk2","avatar_url":"https://avatars0.githubusercontent.com/u/11288996?v=4","gravatar_id":"","url":"https://api.github.com/users/PyGithub","html_url":"https://github.com/PyGithub","followers_url":"https://api.github.com/users/PyGithub/followers","following_url":"https://api.github.com/users/PyGithub/following{/other_user}","gists_url":"https://api.github.com/users/PyGithub/gists{/gist_id}","starred_url":"https://api.github.com/users/PyGithub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/PyGithub/subscriptions","organizations_url":"https://api.github.com/users/PyGithub/orgs","repos_url":"https://api.github.com/users/PyGithub/repos","events_url":"https://api.github.com/users/PyGithub/events{/privacy}","received_events_url":"https://api.github.com/users/PyGithub/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/PyGithub/PyGithub","description":"Typed interactions with the GitHub API v3","fork":false,"url":"https://api.github.com/repos/PyGithub/PyGithub","forks_url":"https://api.github.com/repos/PyGithub/PyGithub/forks","keys_url":"https://api.github.com/repos/PyGithub/PyGithub/keys{/key_id}","collaborators_url":"https://api.github.com/repos/PyGithub/PyGithub/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/PyGithub/PyGithub/teams","hooks_url":"https://api.github.com/repos/PyGithub/PyGithub/hooks","issue_events_url":"https://api.github.com/repos/PyGithub/PyGithub/issues/events{/number}","events_url":"https://api.github.com/repos/PyGithub/PyGithub/events","assignees_url":"https://api.github.com/repos/PyGithub/PyGithub/assignees{/user}","branches_url":"https://api.github.com/repos/PyGithub/PyGithub/branches{/branch}","tags_url":"https://api.github.com/repos/PyGithub/PyGithub/tags","blobs_url":"https://api.github.com/repos/PyGithub/PyGithub/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/PyGithub/PyGithub/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/PyGithub/PyGithub/git/refs{/sha}","trees_url":"https://api.github.com/repos/PyGithub/PyGithub/git/trees{/sha}","statuses_url":"https://api.github.com/repos/PyGithub/PyGithub/statuses/{sha}","languages_url":"https://api.github.com/repos/PyGithub/PyGithub/languages","stargazers_url":"https://api.github.com/repos/PyGithub/PyGithub/stargazers","contributors_url":"https://api.github.com/repos/PyGithub/PyGithub/contributors","subscribers_url":"https://api.github.com/repos/PyGithub/PyGithub/subscribers","subscription_url":"https://api.github.com/repos/PyGithub/PyGithub/subscription","commits_url":"https://api.github.com/repos/PyGithub/PyGithub/commits{/sha}","git_commits_url":"https://api.github.com/repos/PyGithub/PyGithub/git/commits{/sha}","comments_url":"https://api.github.com/repos/PyGithub/PyGithub/comments{/number}","issue_comment_url":"https://api.github.com/repos/PyGithub/PyGithub/issues/comments{/number}","contents_url":"https://api.github.com/repos/PyGithub/PyGithub/contents/{+path}","compare_url":"https://api.github.com/repos/PyGithub/PyGithub/compare/{base}...{head}","merges_url":"https://api.github.com/repos/PyGithub/PyGithub/merges","archive_url":"https://api.github.com/repos/PyGithub/PyGithub/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/PyGithub/PyGithub/downloads","issues_url":"https://api.github.com/repos/PyGithub/PyGithub/issues{/number}","pulls_url":"https://api.github.com/repos/PyGithub/PyGithub/pulls{/number}","milestones_url":"https://api.github.com/repos/PyGithub/PyGithub/milestones{/number}","notifications_url":"https://api.github.com/repos/PyGithub/PyGithub/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/PyGithub/PyGithub/labels{/name}","releases_url":"https://api.github.com/repos/PyGithub/PyGithub/releases{/id}","deployments_url":"https://api.github.com/repos/PyGithub/PyGithub/deployments","created_at":"2012-02-25T12:53:47Z","updated_at":"2018-12-01T07:01:06Z","pushed_at":"2018-12-02T11:35:58Z","git_url":"git://github.com/PyGithub/PyGithub.git","ssh_url":"git@github.com:PyGithub/PyGithub.git","clone_url":"https://github.com/PyGithub/PyGithub.git","svn_url":"https://github.com/PyGithub/PyGithub","homepage":"https://pygithub.readthedocs.io/","size":11536,"stargazers_count":2232,"watchers_count":2232,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":757,"mirror_url":null,"archived":false,"open_issues_count":57,"license":{"key":"lgpl-3.0","name":"GNU Lesser General Public License v3.0","spdx_id":"LGPL-3.0","url":"https://api.github.com/licenses/lgpl-3.0","node_id":"MDc6TGljZW5zZTEy"},"forks":757,"open_issues":57,"watchers":2232,"default_branch":"master"},"network_count":757,"subscribers_count":3} + diff --git a/github/tests/ReplayData/Traffic.testGetClones.txt b/github/tests/ReplayData/Traffic.testGetClones.txt new file mode 100644 index 00000000..946bf0fd --- /dev/null +++ b/github/tests/ReplayData/Traffic.testGetClones.txt @@ -0,0 +1,11 @@ +https +GET +api.github.com +None +/repos/jkufro/PyGithub/traffic/clones +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Sun, 02 Dec 2018 17:25:20 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4988'), ('X-RateLimit-Reset', '1543775101'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP'), ('ETag', 'W/"99f62fd904c91505ef4f1f8b89d22c08"'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'F408:56B2:D8A13F:1E6EC1B:5C041580')] +{"count":4,"uniques":4,"clones":[{"timestamp":"2018-11-27T00:00:00Z","count":4,"uniques":4}]} + diff --git a/github/tests/ReplayData/Traffic.testGetPaths.txt b/github/tests/ReplayData/Traffic.testGetPaths.txt new file mode 100644 index 00000000..ed14320f --- /dev/null +++ b/github/tests/ReplayData/Traffic.testGetPaths.txt @@ -0,0 +1,11 @@ +https +GET +api.github.com +None +/repos/jkufro/PyGithub/traffic/popular/paths +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Sun, 02 Dec 2018 18:37:44 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4994'), ('X-RateLimit-Reset', '1543779296'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP'), ('ETag', 'W/"b886e79ff0cee5a1b67a5efa00b3ca0f"'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'F7B9:56B2:DB4511:1ECCC1B:5C042678')] +[{"path":"/jkufro/PyGithub","title":"jkufro/PyGithub: Typed interactions with the GitHub API v3","count":23,"uniques":4},{"path":"/jkufro/PyGithub/tree/traffic_endpoints","title":"jkufro/PyGithub at traffic_endpoints","count":13,"uniques":4},{"path":"/jkufro/PyGithub/blob/master/github/Repository.py","title":"PyGithub/Repository.py at master jkufro/PyGithub","count":6,"uniques":3},{"path":"/jkufro/PyGithub/branches","title":"Branches jkufro/PyGithub","count":6,"uniques":1},{"path":"/jkufro/PyGithub/commits/traffic_endpoints","title":"Commits jkufro/PyGithub","count":4,"uniques":2},{"path":"/jkufro/PyGithub/tree/traffic_endpoints/github","title":"PyGithub/github at traffic_endpoints jkufro/PyGithub","count":4,"uniques":2},{"path":"/jkufro/PyGithub/commit/f309070d99a58336a577bf7c88c49773fe3f16a2","title":"better pep8 compliance and delted unused Traffic.py file jkufro/PyGithub@f3...","count":3,"uniques":2},{"path":"/jkufro/PyGithub/commits","title":"Commits jkufro/PyGithub","count":3,"uniques":1},{"path":"/jkufro/PyGithub/commit/1fd7e391735715ad7f752e230a45eba891927e64","title":"made placeholder classes jkufro/PyGithub@1fd7e39","count":2,"uniques":1},{"path":"/jkufro/PyGithub/commit/5296fb83e0a8ab3fdcbc1b7a3a28beae4f8f38bb","title":"clone and view class jkufro/PyGithub@5296fb8","count":2,"uniques":1}] + diff --git a/github/tests/ReplayData/Traffic.testGetReferrers.txt b/github/tests/ReplayData/Traffic.testGetReferrers.txt new file mode 100644 index 00000000..4365a83e --- /dev/null +++ b/github/tests/ReplayData/Traffic.testGetReferrers.txt @@ -0,0 +1,11 @@ +https +GET +api.github.com +None +/repos/jkufro/PyGithub/traffic/popular/referrers +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Sun, 02 Dec 2018 17:25:02 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4997'), ('X-RateLimit-Reset', '1543775101'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP'), ('ETag', 'W/"033913cf8de0341149e2639c12d7a240"'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'F3F4:56B2:D89E29:1E6E41C:5C04156D')] +[{"referrer":"github.com","count":5,"uniques":1}] + diff --git a/github/tests/ReplayData/Traffic.testGetViews.txt b/github/tests/ReplayData/Traffic.testGetViews.txt new file mode 100644 index 00000000..65a67256 --- /dev/null +++ b/github/tests/ReplayData/Traffic.testGetViews.txt @@ -0,0 +1,11 @@ +https +GET +api.github.com +None +/repos/jkufro/PyGithub/traffic/views +{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'} +None +200 +[('Server', 'GitHub.com'), ('Date', 'Sun, 02 Dec 2018 17:25:15 GMT'), ('Content-Type', 'application/json; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Status', '200 OK'), ('X-RateLimit-Limit', '5000'), ('X-RateLimit-Remaining', '4991'), ('X-RateLimit-Reset', '1543775101'), ('Cache-Control', 'private, max-age=60, s-maxage=60'), ('Vary', 'Accept, Authorization, Cookie, X-GitHub-OTP'), ('ETag', 'W/"47961c20927a4d019bc73ee47bd8fe79"'), ('X-GitHub-Media-Type', 'github.v3; format=json'), ('Access-Control-Expose-Headers', 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type'), ('Access-Control-Allow-Origin', '*'), ('Strict-Transport-Security', 'max-age=31536000; includeSubdomains; preload'), ('X-Frame-Options', 'deny'), ('X-Content-Type-Options', 'nosniff'), ('X-XSS-Protection', '1; mode=block'), ('Referrer-Policy', 'origin-when-cross-origin, strict-origin-when-cross-origin'), ('Content-Security-Policy', "default-src 'none'"), ('Content-Encoding', 'gzip'), ('X-GitHub-Request-Id', 'F402:56B3:75FF23:12D1E43:5C04157B')] +{"count":93,"uniques":4,"views":[{"timestamp":"2018-11-27T00:00:00Z","count":56,"uniques":4},{"timestamp":"2018-11-28T00:00:00Z","count":6,"uniques":2},{"timestamp":"2018-11-30T00:00:00Z","count":18,"uniques":1},{"timestamp":"2018-12-01T00:00:00Z","count":4,"uniques":1},{"timestamp":"2018-12-02T00:00:00Z","count":9,"uniques":3}]} + diff --git a/github/tests/Traffic.py b/github/tests/Traffic.py new file mode 100644 index 00000000..6bde4396 --- /dev/null +++ b/github/tests/Traffic.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- + +############################ Copyrights and license ############################ +# # +# Copyright 2018 Justin Kufro # +# Copyright 2018 Ivan Minno # +# Copyright 2018 Zilei Gu # +# Copyright 2018 Yves Zumbach # +# Copyright 2018 Leying Chen # +# # +# This file is part of PyGithub. # +# http://pygithub.readthedocs.io/ # +# # +# PyGithub is free software: you can redistribute it and/or modify it under # +# the terms of the GNU Lesser General Public License as published by the Free # +# Software Foundation, either version 3 of the License, or (at your option) # +# any later version. # +# # +# PyGithub is distributed in the hope that it will be useful, but WITHOUT ANY # +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # +# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more # +# details. # +# # +# You should have received a copy of the GNU Lesser General Public License # +# along with PyGithub. If not, see . # +# # +################################################################################ + +import Framework + +import github +import datetime + +class Traffic(Framework.TestCase): + def setUp(self): + Framework.TestCase.setUp(self) + self.user = self.g.get_user() + self.repo = self.user.get_repo("PyGithub") + + def testGetReferrers(self): + referrerResponse = self.repo.get_top_referrers() + self.assertGreaterEqual(len(referrerResponse), 1) + self.assertEqual(referrerResponse[0].uniques, 1) + self.assertEqual(referrerResponse[0].referrer, "github.com") + self.assertEqual(referrerResponse[0].count, 5) + + def testGetPaths(self): + pathsResponse = self.repo.get_top_paths() + self.assertEqual(len(pathsResponse), 10) + self.assertEqual(pathsResponse[0].uniques, 4) + self.assertEqual(pathsResponse[0].count, 23) + self.assertEqual(pathsResponse[0].path, "/jkufro/PyGithub") + self.assertEqual(pathsResponse[0].title, "jkufro/PyGithub: Typed interactions with the GitHub API v3") + + def testGetViews(self): + viewsResponse = self.repo.get_views_traffic() + self.assertEqual(viewsResponse["count"], 93) + self.assertEqual(viewsResponse["uniques"], 4) + self.assertEqual(len(viewsResponse["views"]), 5) + view_obj = viewsResponse["views"][0] + self.assertEqual(view_obj.uniques, 4) + self.assertEqual(view_obj.timestamp, datetime.datetime(2018, 11, 27, 0, 0)) + self.assertEqual(view_obj.count, 56) + + def testGetClones(self): + clonesResponse = self.repo.get_clones_traffic() + self.assertEqual(clonesResponse["count"], 4) + self.assertEqual(clonesResponse["uniques"], 4) + self.assertEqual(len(clonesResponse["clones"]), 1) + clone_obj = clonesResponse["clones"][0] + self.assertEqual(clone_obj.uniques, 4) + self.assertEqual(clone_obj.timestamp, datetime.datetime(2018, 11, 27, 0, 0)) + self.assertEqual(clone_obj.count, 4)