Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'topic/ExposePagination' into develop

  • Loading branch information...
commit 408d76fe5e86d1ec65ceddcc37dbba4955a3c667 2 parents 9818dfc + 6aec5d8
@jacquev6 jacquev6 authored
Showing with 407 additions and 636 deletions.
  1. +84 −79 doc/ReferenceOfClasses.md
  2. +28 −112 github/AuthenticatedUser.py
  3. +4 −16 github/Commit.py
  4. +2 −8 github/Gist.py
  5. +2 −3 github/Github.py
  6. +6 −24 github/Issue.py
  7. +11 −6 github/Legacy.py
  8. +2 −8 github/Milestone.py
  9. +24 −96 github/NamedUser.py
  10. +10 −40 github/Organization.py
  11. +21 −7 github/PaginatedList.py
  12. +8 −32 github/PullRequest.py
  13. +46 −184 github/Repository.py
  14. +4 −16 github/Team.py
  15. +8 −0 test/Github.py
  16. +12 −0 test/PaginatedList.py
  17. +5 −0 test/ReplayData/Github.testLegacySearchReposExplicitPagination.txt
  18. +5 −0 test/ReplayData/Github.testLegacySearchUsersExplicitPagination.txt
  19. +0 −5 test/ReplayData/PaginatedList.setUp.txt
  20. +5 −0 test/ReplayData/PaginatedList.testGetFirstPage.txt
  21. +5 −0 test/ReplayData/PaginatedList.testGetThirdPage.txt
  22. +5 −0 test/ReplayData/PaginatedList.testIntIndexingAfterIteration.txt
  23. +5 −0 test/ReplayData/PaginatedList.testIntIndexingInFirstPage.txt
  24. +5 −0 test/ReplayData/PaginatedList.testIntIndexingInThirdPage.txt
  25. +5 −0 test/ReplayData/PaginatedList.testInterruptedIteration.txt
  26. +5 −0 test/ReplayData/PaginatedList.testInterruptedIterationInSlice.txt
  27. +5 −0 test/ReplayData/PaginatedList.testIteration.txt
  28. +70 −0 test/ReplayData/PaginatedList.testSeveralIterations.txt
  29. +5 −0 test/ReplayData/PaginatedList.testSliceIndexingInFirstPage.txt
  30. +5 −0 test/ReplayData/PaginatedList.testSliceIndexingUntilEnd.txt
  31. +5 −0 test/ReplayData/PaginatedList.testSliceIndexingUntilFourthPage.txt
View
163 doc/ReferenceOfClasses.md
@@ -1,13 +1,6 @@
You don't normaly create instances of any class but `Github`.
You obtain instances through calls to `search_`, `get_` and `create_` methods.
-Methods returning an "iterator of `SomeType`" return an iterator which yields instances of `SomeType`.
-This implements lazy [pagination requests](http://developer.github.com/v3/#pagination).
-You can use this iterator in a `for f in user.get_followers():` loop or with any [itertools](http://docs.python.org/library/itertools.html) functions,
-but you cannot know the number of objects returned before the end of the iteration.
-If that's really what you need, you cant use `len( list( user.get_followers() ) )`, which does all the requests needed to enumerate the user's followers.
-Note that there is often an attribute giving this value (in that case `user.followers`).
-
Class `Github`
==============
@@ -31,12 +24,12 @@ Methods
* `get_organization( login )`: `Organization`
* `get_gist( id )`: `Gist`
* `id`: string
-* `get_gists()`: iterator of `Gist`
-* `get_hooks()`: iterator of `HookDescription`
-* `legacy_search_repos( keyword, [language] )`: iterator of `Repository`
+* `get_gists()`: `PaginatedList` of `Gist`
+* `get_hooks()`: `PaginatedList` of `HookDescription`
+* `legacy_search_repos( keyword, [language] )`: `PaginatedList` of `Repository`
* `keyword`: string
* `language`: string
-* `legacy_search_users( keyword )`: iterator of `NamedUser`
+* `legacy_search_users( keyword )`: `PaginatedList` of `NamedUser`
* `keyword`: string
* `legacy_search_user_by_email( email )`: `NamedUser`
* `email`: string
@@ -44,6 +37,18 @@ Methods
* `text`: string
* `context`: `Repository`
+Class `PaginatedList`
+=====================
+
+This class implements lazy [pagination requests](http://developer.github.com/v3/#pagination) and hides pagination from you. It is the return type of `get_` methods that return a collection.
+
+You can iterate on it in a `for f in user.get_followers():` loop or with any [itertools](http://docs.python.org/library/itertools.html) functions.
+
+You cannot know the number of objects returned before the end of the iteration. If that's *really* what you need, you cant use `len( list( user.get_followers() ) )`,
+which does all the requests needed to enumerate the user's followers. Note that there is often an attribute giving this value (in that case `user.followers`).
+
+You can also call `get_page( page )` where `page` is an integer starting at 0, to explicitely get a specific page if you don't want to hide pagination.
+
Class `GithubException`
=======================
@@ -91,7 +96,7 @@ Authorizations
* `note_url`: string
* `get_authorization( id )`: `Authorization`
* `id`: integer
-* `get_authorizations()`: iterator of `Authorization`
+* `get_authorizations()`: `PaginatedList` of `Authorization`
Emails
------
@@ -103,19 +108,19 @@ Emails
Events
------
-* `get_events()`: iterator of `Event`
-* `get_organization_events( org )`: iterator of `Event`
+* `get_events()`: `PaginatedList` of `Event`
+* `get_organization_events( org )`: `PaginatedList` of `Event`
* `org`: `Organization`
Followers
---------
-* `get_followers()`: iterator of `NamedUser`
+* `get_followers()`: `PaginatedList` of `NamedUser`
Following
---------
* `add_to_following( following )`
* `following`: `NamedUser`
-* `get_following()`: iterator of `NamedUser`
+* `get_following()`: `PaginatedList` of `NamedUser`
* `has_in_following( following )`: bool
* `following`: `NamedUser`
* `remove_from_following( following )`
@@ -132,12 +137,12 @@ Gists
* `public`: bool
* `files`: dict of string to `InputFileContent`
* `description`: string
-* `get_gists()`: iterator of `Gist`
-* `get_starred_gists()`: iterator of `Gist`
+* `get_gists()`: `PaginatedList` of `Gist`
+* `get_starred_gists()`: `PaginatedList` of `Gist`
Issues
------
-* `get_issues()`: iterator of `Issue`
+* `get_issues()`: `PaginatedList` of `Issue`
Keys
----
@@ -146,7 +151,7 @@ Keys
* `key`: string
* `get_key( id )`: `UserKey`
* `id`: integer
-* `get_keys()`: iterator of `UserKey`
+* `get_keys()`: `PaginatedList` of `UserKey`
Modification
------------
@@ -161,7 +166,7 @@ Modification
Orgs
----
-* `get_orgs()`: iterator of `Organization`
+* `get_orgs()`: `PaginatedList` of `Organization`
Repos
-----
@@ -175,7 +180,7 @@ Repos
* `has_downloads`: bool
* `get_repo( name )`: `Repository`
* `name`: string
-* `get_repos( [type, sort, direction] )`: iterator of `Repository`
+* `get_repos( [type, sort, direction] )`: `PaginatedList` of `Repository`
* `type`: string
* `sort`: string
* `direction`: string
@@ -184,7 +189,7 @@ Starred
-------
* `add_to_starred( starred )`
* `starred`: `Repository`
-* `get_starred()`: iterator of `Repository`
+* `get_starred()`: `PaginatedList` of `Repository`
* `has_in_starred( starred )`: bool
* `starred`: `Repository`
* `remove_from_starred( starred )`
@@ -194,7 +199,7 @@ Subscriptions
-------------
* `add_to_subscriptions( subscription )`
* `subscription`: `Repository`
-* `get_subscriptions()`: iterator of `Repository`
+* `get_subscriptions()`: `PaginatedList` of `Repository`
* `has_in_subscriptions( subscription )`: bool
* `subscription`: `Repository`
* `remove_from_subscriptions( subscription )`
@@ -204,7 +209,7 @@ Watched
-------
* `add_to_watched( watched )`
* `watched`: `Repository`
-* `get_watched()`: iterator of `Repository`
+* `get_watched()`: `PaginatedList` of `Repository`
* `has_in_watched( watched )`: bool
* `watched`: `Repository`
* `remove_from_watched( watched )`
@@ -275,7 +280,7 @@ Comments
* `line`: integer
* `path`: string
* `position`: integer
-* `get_comments()`: iterator of `CommitComment`
+* `get_comments()`: `PaginatedList` of `CommitComment`
Statuses
--------
@@ -283,7 +288,7 @@ Statuses
* `state`: string
* `target_url`: string
* `description`: string
-* `get_statuses()`: iterator of `CommitStatus`
+* `get_statuses()`: `PaginatedList` of `CommitStatus`
Class `CommitComment`
=====================
@@ -450,7 +455,7 @@ Comments
* `body`: string
* `get_comment( id )`: `GistComment`
* `id`: integer
-* `get_comments()`: iterator of `GistComment`
+* `get_comments()`: `PaginatedList` of `GistComment`
Deletion
--------
@@ -691,18 +696,18 @@ Comments
* `body`: string
* `get_comment( id )`: `IssueComment`
* `id`: integer
-* `get_comments()`: iterator of `IssueComment`
+* `get_comments()`: `PaginatedList` of `IssueComment`
Events
------
-* `get_events()`: iterator of `IssueEvent`
+* `get_events()`: `PaginatedList` of `IssueEvent`
Labels
------
* `add_to_labels( label, ... )`
* `label`: `Label`
* `delete_labels()`
-* `get_labels()`: iterator of `Label`
+* `get_labels()`: `PaginatedList` of `Label`
* `remove_from_labels( label )`
* `label`: `Label`
* `set_labels( label, ... )`
@@ -803,7 +808,7 @@ Deletion
Labels
------
-* `get_labels()`: iterator of `Label`
+* `get_labels()`: `PaginatedList` of `Label`
Modification
------------
@@ -847,18 +852,18 @@ Attributes
Events
------
-* `get_events()`: iterator of `Event`
-* `get_public_events()`: iterator of `Event`
-* `get_received_events()`: iterator of `Event`
-* `get_public_received_events()`: iterator of `Event`
+* `get_events()`: `PaginatedList` of `Event`
+* `get_public_events()`: `PaginatedList` of `Event`
+* `get_received_events()`: `PaginatedList` of `Event`
+* `get_public_received_events()`: `PaginatedList` of `Event`
Followers
---------
-* `get_followers()`: iterator of `NamedUser`
+* `get_followers()`: `PaginatedList` of `NamedUser`
Following
---------
-* `get_following()`: iterator of `NamedUser`
+* `get_following()`: `PaginatedList` of `NamedUser`
Gists
-----
@@ -866,30 +871,30 @@ Gists
* `public`: bool
* `files`: dict of string to `InputFileContent`
* `description`: string
-* `get_gists()`: iterator of `Gist`
+* `get_gists()`: `PaginatedList` of `Gist`
Orgs
----
-* `get_orgs()`: iterator of `Organization`
+* `get_orgs()`: `PaginatedList` of `Organization`
Repos
-----
* `get_repo( name )`: `Repository`
* `name`: string
-* `get_repos( [type] )`: iterator of `Repository`
+* `get_repos( [type] )`: `PaginatedList` of `Repository`
* `type`: string
Starred
-------
-* `get_starred()`: iterator of `Repository`
+* `get_starred()`: `PaginatedList` of `Repository`
Subscriptions
-------------
-* `get_subscriptions()`: iterator of `Repository`
+* `get_subscriptions()`: `PaginatedList` of `Repository`
Watched
-------
-* `get_watched()`: iterator of `Repository`
+* `get_watched()`: `PaginatedList` of `Repository`
Class `Organization`
====================
@@ -923,7 +928,7 @@ Attributes
Events
------
-* `get_events()`: iterator of `Event`
+* `get_events()`: `PaginatedList` of `Event`
Forking
-------
@@ -932,7 +937,7 @@ Forking
Members
-------
-* `get_members()`: iterator of `NamedUser`
+* `get_members()`: `PaginatedList` of `NamedUser`
* `has_in_members( member )`: bool
* `member`: `NamedUser`
* `remove_from_members( member )`
@@ -952,7 +957,7 @@ Public_members
--------------
* `add_to_public_members( public_member )`
* `public_member`: `NamedUser`
-* `get_public_members()`: iterator of `NamedUser`
+* `get_public_members()`: `PaginatedList` of `NamedUser`
* `has_in_public_members( public_member )`: bool
* `public_member`: `NamedUser`
* `remove_from_public_members( public_member )`
@@ -971,7 +976,7 @@ Repos
* `team_id`: `Team`
* `get_repo( name )`: `Repository`
* `name`: string
-* `get_repos( [type] )`: iterator of `Repository`
+* `get_repos( [type] )`: `PaginatedList` of `Repository`
* `type`: string
Teams
@@ -982,7 +987,7 @@ Teams
* `permission`: string
* `get_team( id )`: `Team`
* `id`: integer
-* `get_teams()`: iterator of `Team`
+* `get_teams()`: `PaginatedList` of `Team`
Class `Permissions`
===================
@@ -1044,15 +1049,15 @@ Review comments
* `position`: integer
* `get_comment( id )` or `get_review_comment( id )`: `PullRequestComment`
* `id`: integer
-* `get_comments()` or `get_review_comments()`: iterator of `PullRequestComment`
+* `get_comments()` or `get_review_comments()`: `PaginatedList` of `PullRequestComment`
Commits
-------
-* `get_commits()`: iterator of `Commit`
+* `get_commits()`: `PaginatedList` of `Commit`
Files
-----
-* `get_files()`: iterator of `File`
+* `get_files()`: `PaginatedList` of `File`
Issue_comments
--------------
@@ -1060,7 +1065,7 @@ Issue_comments
* `body`: string
* `get_issue_comment( id )`: `IssueComment`
* `id`: integer
-* `get_issue_comments()`: iterator of `IssueComment`
+* `get_issue_comments()`: `PaginatedList` of `IssueComment`
Merging
-------
@@ -1165,7 +1170,7 @@ Comparison
Assignees
---------
-* `get_assignees()`: iterator of `NamedUser`
+* `get_assignees()`: `PaginatedList` of `NamedUser`
* `has_in_assignees( assignee )`: bool
* `assignee`: `NamedUser`
@@ -1173,13 +1178,13 @@ Branches
--------
* `get_branch( branch )`: `Branch`
* `branch`: string
-* `get_branches()`: iterator of `Branch`
+* `get_branches()`: `PaginatedList` of `Branch`
Collaborators
-------------
* `add_to_collaborators( collaborator )`
* `collaborator`: `NamedUser`
-* `get_collaborators()`: iterator of `NamedUser`
+* `get_collaborators()`: `PaginatedList` of `NamedUser`
* `has_in_collaborators( collaborator )`: bool
* `collaborator`: `NamedUser`
* `remove_from_collaborators( collaborator )`
@@ -1189,13 +1194,13 @@ Comments
--------
* `get_comment( id )`: `CommitComment`
* `id`: integer
-* `get_comments()`: iterator of `CommitComment`
+* `get_comments()`: `PaginatedList` of `CommitComment`
Commits
-------
* `get_commit( sha )`: `Commit`
* `sha`: string
-* `get_commits( [sha, path] )`: iterator of `Commit`
+* `get_commits( [sha, path] )`: `PaginatedList` of `Commit`
* `sha`: string
* `path`: string
@@ -1210,7 +1215,7 @@ Contents
Contributors
------------
-* `get_contributors()`: iterator of `NamedUser`
+* `get_contributors()`: `PaginatedList` of `NamedUser`
Deletion
--------
@@ -1225,16 +1230,16 @@ Downloads
* `content_type`: string
* `get_download( id )`: `Download`
* `id`: integer
-* `get_downloads()`: iterator of `Download`
+* `get_downloads()`: `PaginatedList` of `Download`
Events
------
-* `get_events()`: iterator of `Event`
-* `get_network_events()`: iterator of `Event`
+* `get_events()`: `PaginatedList` of `Event`
+* `get_network_events()`: `PaginatedList` of `Event`
Forks
-----
-* `get_forks()`: iterator of `Repository`
+* `get_forks()`: `PaginatedList` of `Repository`
Git_blobs
---------
@@ -1262,7 +1267,7 @@ Git_refs
* `sha`: string
* `get_git_ref( ref )`: `GitRef`
* `ref`: string
-* `get_git_refs()`: iterator of `GitRef`
+* `get_git_refs()`: `PaginatedList` of `GitRef`
Git_tags
--------
@@ -1293,7 +1298,7 @@ Hooks
* `active`: bool
* `get_hook( id )`: `Hook`
* `id`: integer
-* `get_hooks()`: iterator of `Hook`
+* `get_hooks()`: `PaginatedList` of `Hook`
Issues
------
@@ -1305,7 +1310,7 @@ Issues
* `labels`: list of `Label`
* `get_issue( number )`: `Issue`
* `number`: integer
-* `get_issues( [milestone, state, assignee, mentioned, labels, sort, direction, since] )`: iterator of `Issue`
+* `get_issues( [milestone, state, assignee, mentioned, labels, sort, direction, since] )`: `PaginatedList` of `Issue`
* `milestone`: `Milestone` or "none" or "*"
* `state`: string
* `assignee`: `NamedUser` or "none" or "*"
@@ -1314,7 +1319,7 @@ Issues
* `sort`: string
* `direction`: string
* `since`: datetime.datetime
-* `legacy_search_issues( state, keyword )`: iterator of `Issue`
+* `legacy_search_issues( state, keyword )`: `PaginatedList` of `Issue`
* `state`: "open" or "closed"
* `keyword`: string
@@ -1322,7 +1327,7 @@ Issues_events
-------------
* `get_issues_event( id )`: `IssueEvent`
* `id`: integer
-* `get_issues_events()`: iterator of `IssueEvent`
+* `get_issues_events()`: `PaginatedList` of `IssueEvent`
Keys
----
@@ -1331,7 +1336,7 @@ Keys
* `key`: string
* `get_key( id )`: `RepositoryKey`
* `id`: integer
-* `get_keys()`: iterator of `RepositoryKey`
+* `get_keys()`: `PaginatedList` of `RepositoryKey`
Labels
------
@@ -1340,7 +1345,7 @@ Labels
* `color`: string
* `get_label( name )`: `Label`
* `name`: string
-* `get_labels()`: iterator of `Label`
+* `get_labels()`: `PaginatedList` of `Label`
Languages
---------
@@ -1362,7 +1367,7 @@ Milestones
* `due_on`: date
* `get_milestone( number )`: `Milestone`
* `number`: integer
-* `get_milestones( [state, sort, direction] )`: iterator of `Milestone`
+* `get_milestones( [state, sort, direction] )`: `PaginatedList` of `Milestone`
* `state`: string
* `sort`: string
* `direction`: string
@@ -1388,28 +1393,28 @@ Pulls
* `head`: string
* `get_pull( number )`: `PullRequest`
* `number`: integer
-* `get_pulls( [state] )`: iterator of `PullRequest`
+* `get_pulls( [state] )`: `PaginatedList` of `PullRequest`
* `state`: string
Stargazers
----------
-* `get_stargazers()`: iterator of `NamedUser`
+* `get_stargazers()`: `PaginatedList` of `NamedUser`
Subscribers
-----------
-* `get_subscribers()`: iterator of `NamedUser`
+* `get_subscribers()`: `PaginatedList` of `NamedUser`
Tags
----
-* `get_tags()`: iterator of `Tag`
+* `get_tags()`: `PaginatedList` of `Tag`
Teams
-----
-* `get_teams()`: iterator of `Team`
+* `get_teams()`: `PaginatedList` of `Team`
Watchers
--------
-* `get_watchers()`: iterator of `NamedUser`
+* `get_watchers()`: `PaginatedList` of `NamedUser`
Class `RepositoryKey`
=====================
@@ -1462,7 +1467,7 @@ Members
-------
* `add_to_members( member )`
* `member`: `NamedUser`
-* `get_members()`: iterator of `NamedUser`
+* `get_members()`: `PaginatedList` of `NamedUser`
* `has_in_members( member )`: bool
* `member`: `NamedUser`
* `remove_from_members( member )`
@@ -1478,7 +1483,7 @@ Repos
-----
* `add_to_repos( repo )`
* `repo`: `Repository`
-* `get_repos()`: iterator of `Repository`
+* `get_repos()`: `PaginatedList` of `Repository`
* `has_in_repos( repo )`: bool
* `repo`: `Repository`
* `remove_from_repos( repo )`
View
140 github/AuthenticatedUser.py
@@ -332,17 +332,11 @@ def get_authorization( self, id ):
return Authorization.Authorization( self._requester, data, completed = True )
def get_authorizations( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- "/authorizations",
- None,
- None
- )
return PaginatedList.PaginatedList(
Authorization.Authorization,
self._requester,
- headers,
- data
+ "/authorizations",
+ None
)
def get_emails( self ):
@@ -355,73 +349,43 @@ def get_emails( self ):
return data
def get_events( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- "/events",
- None,
- None
- )
return PaginatedList.PaginatedList(
Event.Event,
self._requester,
- headers,
- data
+ "/events",
+ None
)
def get_followers( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- "/user/followers",
- None,
- None
- )
return PaginatedList.PaginatedList(
NamedUser.NamedUser,
self._requester,
- headers,
- data
+ "/user/followers",
+ None
)
def get_following( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- "/user/following",
- None,
- None
- )
return PaginatedList.PaginatedList(
NamedUser.NamedUser,
self._requester,
- headers,
- data
+ "/user/following",
+ None
)
def get_gists( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- "/gists",
- None,
- None
- )
return PaginatedList.PaginatedList(
Gist.Gist,
self._requester,
- headers,
- data
+ "/gists",
+ None
)
def get_issues( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- "/issues",
- None,
- None
- )
return PaginatedList.PaginatedList(
Issue.Issue,
self._requester,
- headers,
- data
+ "/issues",
+ None
)
def get_key( self, id ):
@@ -435,46 +399,28 @@ def get_key( self, id ):
return UserKey.UserKey( self._requester, data, completed = True )
def get_keys( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- "/user/keys",
- None,
- None
- )
return PaginatedList.PaginatedList(
UserKey.UserKey,
self._requester,
- headers,
- data
+ "/user/keys",
+ None
)
def get_organization_events( self, org ):
assert isinstance( org, Organization.Organization ), org
- headers, data = self._requester.requestAndCheck(
- "GET",
- "/users/" + self.login + "/events/orgs/" + org.login,
- None,
- None
- )
return PaginatedList.PaginatedList(
Event.Event,
self._requester,
- headers,
- data
+ "/users/" + self.login + "/events/orgs/" + org.login,
+ None
)
def get_orgs( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- "/user/orgs",
- None,
- None
- )
return PaginatedList.PaginatedList(
Organization.Organization,
self._requester,
- headers,
- data
+ "/user/orgs",
+ None
)
def get_repo( self, name ):
@@ -498,73 +444,43 @@ def get_repos( self, type = GithubObject.NotSet, sort = GithubObject.NotSet, dir
url_parameters[ "sort" ] = sort
if direction is not GithubObject.NotSet:
url_parameters[ "direction" ] = direction
- headers, data = self._requester.requestAndCheck(
- "GET",
- "/user/repos",
- url_parameters,
- None
- )
return PaginatedList.PaginatedList(
Repository.Repository,
self._requester,
- headers,
- data
+ "/user/repos",
+ url_parameters
)
def get_starred( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- "/user/starred",
- None,
- None
- )
return PaginatedList.PaginatedList(
Repository.Repository,
self._requester,
- headers,
- data
+ "/user/starred",
+ None
)
def get_starred_gists( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- "/gists/starred",
- None,
- None
- )
return PaginatedList.PaginatedList(
Gist.Gist,
self._requester,
- headers,
- data
+ "/gists/starred",
+ None
)
def get_subscriptions( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- "/user/subscriptions",
- None,
- None
- )
return PaginatedList.PaginatedList(
Repository.Repository,
self._requester,
- headers,
- data
+ "/user/subscriptions",
+ None
)
def get_watched( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- "/user/watched",
- None,
- None
- )
return PaginatedList.PaginatedList(
Repository.Repository,
self._requester,
- headers,
- data
+ "/user/watched",
+ None
)
def has_in_following( self, following ):
View
20 github/Commit.py
@@ -105,31 +105,19 @@ def create_status( self, state, target_url = GithubObject.NotSet, description =
return CommitStatus.CommitStatus( self._requester, data, completed = True )
def get_comments( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/comments",
- None,
- None
- )
return PaginatedList.PaginatedList(
CommitComment.CommitComment,
self._requester,
- headers,
- data
+ self.url + "/comments",
+ None
)
def get_statuses( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self._parentUrl( self._parentUrl( self.url ) ) + "/statuses/" + self.sha,
- None,
- None
- )
return PaginatedList.PaginatedList(
CommitStatus.CommitStatus,
self._requester,
- headers,
- data
+ self._parentUrl( self._parentUrl( self.url ) ) + "/statuses/" + self.sha,
+ None
)
@property
View
10 github/Gist.py
@@ -154,17 +154,11 @@ def get_comment( self, id ):
return GistComment.GistComment( self._requester, data, completed = True )
def get_comments( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/comments",
- None,
- None
- )
return PaginatedList.PaginatedList(
GistComment.GistComment,
self._requester,
- headers,
- data
+ self.url + "/comments",
+ None
)
def is_starred( self ):
View
5 github/Github.py
@@ -69,12 +69,11 @@ def get_gist( self, id ):
return Gist.Gist( self.__requester, data, completed = True )
def get_gists( self ):
- headers, data = self.__requester.requestAndCheck( "GET", "/gists/public", None, None )
return PaginatedList.PaginatedList(
Gist.Gist,
self.__requester,
- headers,
- data
+ "/gists/public",
+ None
)
def legacy_search_repos( self, keyword, language = GithubObject.NotSet ):
View
30 github/Issue.py
@@ -183,45 +183,27 @@ def get_comment( self, id ):
return IssueComment.IssueComment( self._requester, data, completed = True )
def get_comments( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/comments",
- None,
- None
- )
return PaginatedList.PaginatedList(
IssueComment.IssueComment,
self._requester,
- headers,
- data
+ self.url + "/comments",
+ None
)
def get_events( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/events",
- None,
- None
- )
return PaginatedList.PaginatedList(
IssueEvent.IssueEvent,
self._requester,
- headers,
- data
+ self.url + "/events",
+ None
)
def get_labels( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/labels",
- None,
- None
- )
return PaginatedList.PaginatedList(
Label.Label,
self._requester,
- headers,
- data
+ self.url + "/labels",
+ None
)
def remove_from_labels( self, label ):
View
17 github/Legacy.py
@@ -15,28 +15,33 @@
class PaginatedList( PaginatedListBase ):
def __init__( self, url, args, requester, key, convert, contentClass ):
- PaginatedListBase.__init__( self, list() )
+ PaginatedListBase.__init__( self )
self.__url = url
self.__args = args
self.__requester = requester
self.__key = key
self.__convert = convert
self.__contentClass = contentClass
- self.__nextPage = 1
+ self.__nextPage = 0
self.__continue = True
- self.__elements = list()
def _couldGrow( self ):
return self.__continue
def _fetchNextPage( self ):
- if self.__nextPage != 1:
- self.__args[ "start_page" ] = self.__nextPage
+ page = self.__nextPage
self.__nextPage += 1
+ return self.get_page( page )
+
+ def get_page( self, page ):
+ assert isinstance( page, int ), page
+ args = dict( self.__args )
+ if page != 0:
+ args[ "start_page" ] = page + 1
headers, data = self.__requester.requestAndCheck(
"GET",
self.__url,
- self.__args,
+ args,
None
)
self.__continue = len( data[ self.__key ] ) > 0
View
10 github/Milestone.py
@@ -106,17 +106,11 @@ def edit( self, title, state = GithubObject.NotSet, description = GithubObject.N
self._useAttributes( data )
def get_labels( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/labels",
- None,
- None
- )
return PaginatedList.PaginatedList(
Label.Label,
self._requester,
- headers,
- data
+ self.url + "/labels",
+ None
)
@property
View
120 github/NamedUser.py
@@ -172,115 +172,67 @@ def create_gist( self, public, files, description = GithubObject.NotSet ):
return Gist.Gist( self._requester, data, completed = True )
def get_events( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/events",
- None,
- None
- )
return PaginatedList.PaginatedList(
Event.Event,
self._requester,
- headers,
- data
+ self.url + "/events",
+ None
)
def get_followers( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/followers",
- None,
- None
- )
return PaginatedList.PaginatedList(
NamedUser,
self._requester,
- headers,
- data
+ self.url + "/followers",
+ None
)
def get_following( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/following",
- None,
- None
- )
return PaginatedList.PaginatedList(
NamedUser,
self._requester,
- headers,
- data
+ self.url + "/following",
+ None
)
def get_gists( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/gists",
- None,
- None
- )
return PaginatedList.PaginatedList(
Gist.Gist,
self._requester,
- headers,
- data
+ self.url + "/gists",
+ None
)
def get_orgs( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/orgs",
- None,
- None
- )
return PaginatedList.PaginatedList(
Organization.Organization,
self._requester,
- headers,
- data
+ self.url + "/orgs",
+ None
)
def get_public_events( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/events/public",
- None,
- None
- )
return PaginatedList.PaginatedList(
Event.Event,
self._requester,
- headers,
- data
+ self.url + "/events/public",
+ None
)
def get_public_received_events( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/received_events/public",
- None,
- None
- )
return PaginatedList.PaginatedList(
Event.Event,
self._requester,
- headers,
- data
+ self.url + "/received_events/public",
+ None
)
def get_received_events( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/received_events",
- None,
- None
- )
return PaginatedList.PaginatedList(
Event.Event,
self._requester,
- headers,
- data
+ self.url + "/received_events",
+ None
)
def get_repo( self, name ):
@@ -298,59 +250,35 @@ def get_repos( self, type = GithubObject.NotSet ):
url_parameters = dict()
if type is not GithubObject.NotSet:
url_parameters[ "type" ] = type
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/repos",
- url_parameters,
- None
- )
return PaginatedList.PaginatedList(
Repository.Repository,
self._requester,
- headers,
- data
+ self.url + "/repos",
+ url_parameters
)
def get_starred( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/starred",
- None,
- None
- )
return PaginatedList.PaginatedList(
Repository.Repository,
self._requester,
- headers,
- data
+ self.url + "/starred",
+ None
)
def get_subscriptions( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/subscriptions",
- None,
- None
- )
return PaginatedList.PaginatedList(
Repository.Repository,
self._requester,
- headers,
- data
+ self.url + "/subscriptions",
+ None
)
def get_watched( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/watched",
- None,
- None
- )
return PaginatedList.PaginatedList(
Repository.Repository,
self._requester,
- headers,
- data
+ self.url + "/watched",
+ None
)
@property
View
50 github/Organization.py
@@ -245,45 +245,27 @@ def edit( self, billing_email = GithubObject.NotSet, blog = GithubObject.NotSet,
self._useAttributes( data )
def get_events( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/events",
- None,
- None
- )
return PaginatedList.PaginatedList(
Event.Event,
self._requester,
- headers,
- data
+ self.url + "/events",
+ None
)
def get_members( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/members",
- None,
- None
- )
return PaginatedList.PaginatedList(
NamedUser.NamedUser,
self._requester,
- headers,
- data
+ self.url + "/members",
+ None
)
def get_public_members( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/public_members",
- None,
- None
- )
return PaginatedList.PaginatedList(
NamedUser.NamedUser,
self._requester,
- headers,
- data
+ self.url + "/public_members",
+ None
)
def get_repo( self, name ):
@@ -301,17 +283,11 @@ def get_repos( self, type = GithubObject.NotSet ):
url_parameters = dict()
if type is not GithubObject.NotSet:
url_parameters[ "type" ] = type
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/repos",
- url_parameters,
- None
- )
return PaginatedList.PaginatedList(
Repository.Repository,
self._requester,
- headers,
- data
+ self.url + "/repos",
+ url_parameters
)
def get_team( self, id ):
@@ -325,17 +301,11 @@ def get_team( self, id ):
return Team.Team( self._requester, data, completed = True )
def get_teams( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/teams",
- None,
- None
- )
return PaginatedList.PaginatedList(
Team.Team,
self._requester,
- headers,
- data
+ self.url + "/teams",
+ None
)
def has_in_members( self, member ):
View
28 github/PaginatedList.py
@@ -14,8 +14,8 @@
import GithubObject
class PaginatedListBase:
- def __init__( self, firstElements ):
- self.__elements = firstElements
+ def __init__( self ):
+ self.__elements = list()
def __getitem__( self, index ):
assert isinstance( index, ( int, slice ) )
@@ -65,24 +65,27 @@ def __finished( self, index ):
return self.__stop is not None and index >= self.__stop
class PaginatedList( PaginatedListBase ):
- def __init__( self, contentClass, requester, headers, data ):
+ def __init__( self, contentClass, requester, firstUrl, firstParams ):
+ PaginatedListBase.__init__( self )
self.__requester = requester
self.__contentClass = contentClass
- PaginatedListBase.__init__( self, self.__extractNewElements( headers, data ) )
+ self.__firstUrl = firstUrl
+ self.__firstParams = firstParams
+ self.__nextUrl = firstUrl
+ self.__nextParams = firstParams
def _couldGrow( self ):
return self.__nextUrl is not None
def _fetchNextPage( self ):
- headers, data = self.__requester.requestAndCheck( "GET", self.__nextUrl, None, None )
- return self.__extractNewElements( headers, data )
+ headers, data = self.__requester.requestAndCheck( "GET", self.__nextUrl, self.__nextParams, None )
- def __extractNewElements( self, headers, data ):
links = self.__parseLinkHeader( headers )
if len( data ) > 0 and "next" in links:
self.__nextUrl = links[ "next" ]
else:
self.__nextUrl = None
+ self.__nextParams = None
return [
self.__contentClass( self.__requester, element, completed = False )
@@ -99,3 +102,14 @@ def __parseLinkHeader( self, headers ):
rel = rel[ 5 : -1 ]
links[ rel ] = url
return links
+
+ def get_page( self, page ):
+ params = dict( self.__firstParams )
+ if page != 0:
+ params[ "page" ] = page + 1
+ headers, data = self.__requester.requestAndCheck( "GET", self.__firstUrl, params, None )
+
+ return [
+ self.__contentClass( self.__requester, element, completed = False )
+ for element in data
+ ]
View
40 github/PullRequest.py
@@ -224,45 +224,27 @@ def get_comments( self ):
return self.get_review_comments()
def get_review_comments( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/comments",
- None,
- None
- )
return PaginatedList.PaginatedList(
PullRequestComment.PullRequestComment,
self._requester,
- headers,
- data
+ self.url + "/comments",
+ None
)
def get_commits( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/commits",
- None,
- None
- )
return PaginatedList.PaginatedList(
Commit.Commit,
self._requester,
- headers,
- data
+ self.url + "/commits",
+ None
)
def get_files( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/files",
- None,
- None
- )
return PaginatedList.PaginatedList(
File.File,
self._requester,
- headers,
- data
+ self.url + "/files",
+ None
)
def get_issue_comment( self, id ):
@@ -276,17 +258,11 @@ def get_issue_comment( self, id ):
return IssueComment.IssueComment( self._requester, data, completed = True )
def get_issue_comments( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self._parentUrl( self._parentUrl( self.url ) ) + "/issues/" + str( self.number ) + "/comments",
- None,
- None
- )
return PaginatedList.PaginatedList(
IssueComment.IssueComment,
self._requester,
- headers,
- data
+ self._parentUrl( self._parentUrl( self.url ) ) + "/issues/" + str( self.number ) + "/comments",
+ None
)
def is_merged( self ):
View
230 github/Repository.py
@@ -510,17 +510,11 @@ def get_archive_link( self, archive_format, ref = GithubObject.NotSet ):
return headers[ "location" ]
def get_assignees( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/assignees",
- None,
- None
- )
return PaginatedList.PaginatedList(
NamedUser.NamedUser,
self._requester,
- headers,
- data
+ self.url + "/assignees",
+ None
)
def get_branch( self, branch ):
@@ -534,31 +528,19 @@ def get_branch( self, branch ):
return Branch.Branch( self._requester, data, completed = True )
def get_branches( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/branches",
- None,
- None
- )
return PaginatedList.PaginatedList(
Branch.Branch,
self._requester,
- headers,
- data
+ self.url + "/branches",
+ None
)
def get_collaborators( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/collaborators",
- None,
- None
- )
return PaginatedList.PaginatedList(
NamedUser.NamedUser,
self._requester,
- headers,
- data
+ self.url + "/collaborators",
+ None
)
def get_comment( self, id ):
@@ -572,17 +554,11 @@ def get_comment( self, id ):
return CommitComment.CommitComment( self._requester, data, completed = True )
def get_comments( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/comments",
- None,
- None
- )
return PaginatedList.PaginatedList(
CommitComment.CommitComment,
self._requester,
- headers,
- data
+ self.url + "/comments",
+ None
)
def get_commit( self, sha ):
@@ -603,17 +579,11 @@ def get_commits( self, sha = GithubObject.NotSet, path = GithubObject.NotSet ):
url_parameters[ "sha" ] = sha
if path is not GithubObject.NotSet:
url_parameters[ "path" ] = path
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/commits",
- url_parameters,
- None
- )
return PaginatedList.PaginatedList(
Commit.Commit,
self._requester,
- headers,
- data
+ self.url + "/commits",
+ url_parameters
)
def get_contents( self, path ):
@@ -627,17 +597,11 @@ def get_contents( self, path ):
return ContentFile.ContentFile( self._requester, data, completed = True )
def get_contributors( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/contributors",
- None,
- None
- )
return PaginatedList.PaginatedList(
NamedUser.NamedUser,
self._requester,
- headers,
- data
+ self.url + "/contributors",
+ None
)
def get_download( self, id ):
@@ -651,45 +615,27 @@ def get_download( self, id ):
return Download.Download( self._requester, data, completed = True )
def get_downloads( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/downloads",
- None,
- None
- )
return PaginatedList.PaginatedList(
Download.Download,
self._requester,
- headers,
- data
+ self.url + "/downloads",
+ None
)
def get_events( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/events",
- None,
- None
- )
return PaginatedList.PaginatedList(
Event.Event,
self._requester,
- headers,
- data
+ self.url + "/events",
+ None
)
def get_forks( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/forks",
- None,
- None
- )
return PaginatedList.PaginatedList(
Repository,
self._requester,
- headers,
- data
+ self.url + "/forks",
+ None
)
def get_git_blob( self, sha ):
@@ -723,17 +669,11 @@ def get_git_ref( self, ref ):
return GitRef.GitRef( self._requester, data, completed = True )
def get_git_refs( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/git/refs",
- None,
- None
- )
return PaginatedList.PaginatedList(
GitRef.GitRef,
self._requester,
- headers,
- data
+ self.url + "/git/refs",
+ None
)
def get_git_tag( self, sha ):
@@ -771,17 +711,11 @@ def get_hook( self, id ):
return Hook.Hook( self._requester, data, completed = True )
def get_hooks( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/hooks",
- None,
- None
- )
return PaginatedList.PaginatedList(
Hook.Hook,
self._requester,
- headers,
- data
+ self.url + "/hooks",
+ None
)
def get_issue( self, number ):
@@ -826,17 +760,11 @@ def get_issues( self, milestone = GithubObject.NotSet, state = GithubObject.NotS
url_parameters[ "direction" ] = direction
if since is not GithubObject.NotSet:
url_parameters[ "since" ] = since.strftime( "%Y-%m-%dT%H:%M:%SZ" )
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/issues",
- url_parameters,
- None
- )
return PaginatedList.PaginatedList(
Issue.Issue,
self._requester,
- headers,
- data
+ self.url + "/issues",
+ url_parameters
)
def get_issues_event( self, id ):
@@ -850,17 +778,11 @@ def get_issues_event( self, id ):
return IssueEvent.IssueEvent( self._requester, data, completed = True )
def get_issues_events( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/issues/events",
- None,
- None
- )
return PaginatedList.PaginatedList(
IssueEvent.IssueEvent,
self._requester,
- headers,
- data
+ self.url + "/issues/events",
+ None
)
def get_key( self, id ):
@@ -874,17 +796,11 @@ def get_key( self, id ):
return RepositoryKey.RepositoryKey( self._requester, data, completed = True, repoUrl = self._url )
def get_keys( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/keys",
- None,
- None
- )
return PaginatedList.PaginatedList(
lambda requester, data, completed: RepositoryKey.RepositoryKey( requester, data, completed, repoUrl = self._url ),
self._requester,
- headers,
- data
+ self.url + "/keys",
+ None
)
def get_label( self, name ):
@@ -898,17 +814,11 @@ def get_label( self, name ):
return Label.Label( self._requester, data, completed = True )
def get_labels( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/labels",
- None,
- None
- )
return PaginatedList.PaginatedList(
Label.Label,
self._requester,
- headers,
- data
+ self.url + "/labels",
+ None
)
def get_languages( self ):
@@ -941,31 +851,19 @@ def get_milestones( self, state = GithubObject.NotSet, sort = GithubObject.NotSe
url_parameters[ "sort" ] = sort
if direction is not GithubObject.NotSet:
url_parameters[ "direction" ] = direction
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/milestones",
- url_parameters,
- None
- )
return PaginatedList.PaginatedList(
Milestone.Milestone,
self._requester,
- headers,
- data
+ self.url + "/milestones",
+ url_parameters
)
def get_network_events( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- "/networks/" + self.owner.login + "/" + self.name + "/events",
- None,
- None
- )
return PaginatedList.PaginatedList(
Event.Event,
self._requester,
- headers,
- data
+ "/networks/" + self.owner.login + "/" + self.name + "/events",
+ None
)
def get_pull( self, number ):
@@ -983,17 +881,11 @@ def get_pulls( self, state = GithubObject.NotSet ):
url_parameters = dict()
if state is not GithubObject.NotSet:
url_parameters[ "state" ] = state
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/pulls",
- url_parameters,
- None
- )
return PaginatedList.PaginatedList(
PullRequest.PullRequest,
self._requester,
- headers,
- data
+ self.url + "/pulls",
+ url_parameters
)
def get_readme( self ):
@@ -1006,73 +898,43 @@ def get_readme( self ):
return ContentFile.ContentFile( self._requester, data, completed = True )
def get_stargazers( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/stargazers",
- None,
- None
- )
return PaginatedList.PaginatedList(
NamedUser.NamedUser,
self._requester,
- headers,
- data
+ self.url + "/stargazers",
+ None
)
def get_subscribers( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/subscribers",
- None,
- None
- )
return PaginatedList.PaginatedList(
NamedUser.NamedUser,
self._requester,
- headers,
- data
+ self.url + "/subscribers",
+ None
)
def get_tags( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/tags",
- None,
- None
- )
return PaginatedList.PaginatedList(
Tag.Tag,
self._requester,
- headers,
- data
+ self.url + "/tags",
+ None
)
def get_teams( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/teams",
- None,
- None
- )
return PaginatedList.PaginatedList(
Team.Team,
self._requester,
- headers,
- data
+ self.url + "/teams",
+ None
)
def get_watchers( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/watchers",
- None,
- None
- )
return PaginatedList.PaginatedList(
NamedUser.NamedUser,
self._requester,
- headers,
- data
+ self.url + "/watchers",
+ None
)
def has_in_assignees( self, assignee ):
View
20 github/Team.py
@@ -91,31 +91,19 @@ def edit( self, name, permission = GithubObject.NotSet ):
self._useAttributes( data )
def get_members( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/members",
- None,
- None
- )
return PaginatedList.PaginatedList(
NamedUser.NamedUser,
self._requester,
- headers,
- data
+ self.url + "/members",
+ None
)
def get_repos( self ):
- headers, data = self._requester.requestAndCheck(
- "GET",
- self.url + "/repos",
- None,
- None
- )
return PaginatedList.PaginatedList(
Repository.Repository,
self._requester,
- headers,
- data
+ self.url + "/repos",
+ None
)
def has_in_members( self, member ):
View
8 test/Github.py
@@ -48,6 +48,10 @@ def testLegacySearchReposPagination( self ):
repos = self.g.legacy_search_repos( "document" )
self.assertListKeyBegin( repos, lambda r: r.name, [ "git", "nimbus", "kss", "sstoolkit", "lawnchair", "appledoc", "jQ.Mobi", "ipython", "mongoengine", "ravendb", "substance", "symfony-docs", "JavaScript-Garden", "DocSets-for-iOS", "yard", "phpDocumentor2", "phpsh", "Tangle", "Ingredients", "documentjs", "xhp", "couchdb-lucene", "dox", "magento2", "javascriptmvc", "FastPdfKit", "roar", "DocumentUp", "NoRM", "jsdoc", "tagger", "mongodb-csharp", "php-github-api", "beautiful-docs", "mongodb-odm", "iodocs", "seesaw", "bcx-api", "developer.github.com", "amqp", "docsplit", "pycco", "standards-and-practices", "tidy-html5", "redis-doc", "tomdoc", "docs", "flourish", "userguide", "swagger-ui", "rfc", "Weasel-Diesel", "yuidoc", "apigen", "document-viewer", "develop.github.com", "Shanty-Mongo", "PTShowcaseViewController", "gravatar_image_tag", "api-wow-docs", "mongoid-tree", "safari-json-formatter", "mayan", "orm-documentation", "jsfiddle-docs-alpha", "core", "documentcloud", "flexible-nav", "writeCapture", "readium", "xmldocument", "Documentation-Examples", "grails-doc", "stdeb", "aws-autoscaling", "voteable_mongo", "review", "spreadsheet_on_rails", "UKSyntaxColoredTextDocument", "mandango", "bdoc", "Documentation", "documents.com", "rghost", "ticket_mule", "vendo", "khan-api", "spring-data-document-examples", "rspec_api_documentation", "axlsx", "phpdox", "documentation", "Sami", "innershiv", "doxyclean", "documents", "rvm-site", "jqapi", "documentation", "hadoopy", "VichUploaderBundle", "pdoc", "documentation", "wii-js", "oss-docs", "scala-maven-plugin", "Documents", "documenter", "behemoth", "documentation", "documentation", "propelorm.github.com", "Kobold2D", "AutoObjectDocumentation", "php-mongodb-admin", "django-mongokit", "puppet-docs", "docs", "Document", "vendorer", "symfony1-docs", "shocco", "documentation", "jog", "docs", "documentation", "documentation", "documentation", "documentation", "Documentation", "documentation", "documentation", "phpunit-documentation", "ADCtheme", "NelmioApiDocBundle", "iCloud-Singleton-CloudMe", "Documentation", "document", "document_mapper", "heroku-docs", "couchdb-odm", "documentation", "documentation", "document", "documentation", "NanoStore", "documentation", "Documentation", "documentation", "Documentation", "documentation", "document", "documentation", "documentation", "Documentation", "Documentation", "grendel", "ceylon-compiler", "mbtiles-spec", "documentation", "documents", "documents", "Documents", "Documentation", "documentation", "Documentation", "documentation", "documents", "Documentation", "documentation", "documentation", "documents", "Documentation", "documentation", "documenter", "documentation", "documents", "Documents", "documents", "documents", "documentation", "Document", "document", "rdoc", "mongoid_token", "travis-ci.github.com", "Documents", "Documents", "documents", "Document", "Documentation", "documents", "Documents", "Documentation", "documents", "documents", "documents", "documentation", "Documents", "Document", "documents", "documents", "Documentation", "Documentation", "Document", "documents", "Documents", "Documents", "Documentation", "Documents", "documents", "Documents", "document", "documents", "Documentation", "Documents", "documents", "documents", "Documents", "documents", "Documentation", "documentation", "Document", "Documents", "documents", "documents", "documents", "Documentation", "Documentation", "Documents", "Documents", "Documents", "Documenter", "document", "Documentation", "Documents", "Documents", "documentation", "documentation", "Document", "Documents", "Documentation", "Documentation", "Documents", "documents", "Documents", "document", "documentation", "Documents", "documentation", "documentation", "documentation", "Documentation", "Documents", "Documents", "documentation", "Documents", "Documents", "documentation", "documentation", "documents", "Documentation", "documents", "documentation", "Documentation", "Documents", "documentation", "documentation", "documents", "documentation", "Umbraco5Docs", "documents", "Documents", "Documentation", "documents", "document", "documents", "document", "documents", "documentation", "Documents", "documents", "document", "Documents", "Documentation", "Documentation", "documentation", "Documentation", "document", "documentation", "documents", "documents", "Documentations", "document", "documentation", "Documentation", "Document", "Documents", "Documents", "Document" ] )
+ def testLegacySearchReposExplicitPagination( self ):
+ repos = self.g.legacy_search_repos( "python" )
+ self.assertEqual( [ r.name for r in repos.get_page( 4 ) ], [ "assetic", "cartodb", "cuisine", "gae-sessions", "geoalchemy2", "Multicorn", "wmfr-timeline", "redis-rdb-tools", "applet-workflows", "TweetBuff", "groovy-core", "StarTrekGame", "Nuevo", "Cupid", "node-sqlserver", "Magnet2Torrent", "GroundControl", "mock-django", "4bit", "mock-django", "Fabulous", "SFML", "pydicas", "flixel", "up", "mongrel2", "SimpleHTTPServerJs", "ultimos", "Archipel", "JSbooks", "nova", "nodebox", "simplehttp", "dablooms", "solarized", "landslide", "jQuery-File-Upload", "jQuery-File-Upload", "jQuery-File-Upload", "password-manager", "electrum", "twitter_nlp", "djangbone", "pyxfst", "node-gyp", "flare", "www.gittip.com", "wymeditor", "Kokobox", "MyCQ", "runwalk", "git-sweep", "HPCPythonSC2012", "sundown", "node2dm", "statirator", "fantastic-futures", "chainsaw", "itcursos-gerenciador-tarefas", "TideSDK", "genmaybot", "melpa", "ConnectedWire", "tarantool", "anserindicus_sn", "luvit", "Minecraft-Overviewer", "Iconic", "pyist.net", "wikibok", "mejorenvo-scraper", "NewsBlur", "SocketRocket", "spf13-vim", "IWantToWorkAtGloboCom", "ruby-style-guide", "aery32-refguide", "fafsite", "compsense_demo", "enaml", "mpi4py", "fi.pycon.org", "scikits-image", "scikits-image", "uni", "mako.vim", "mako.vim", "slumber", "de-composer", "nvm", "helloshopply", "Alianza", "vimfiles", "socorro-crashstats", "menu", "analytics", "elFinder", "riak_wiki", "livestreamer", "git-goggles" ] )
+
def testLegacySearchReposWithLanguage( self ):
repos = self.g.legacy_search_repos( "document", language = "Python" )
self.assertListKeyBegin( repos, lambda r: r.name, [ "ipython", "mongoengine", "tagger" ] )
@@ -69,6 +73,10 @@ def testLegacySearchUsers( self ):
def testLegacySearchUsersPagination( self ):
self.assertEqual( len( list( self.g.legacy_search_users( "Lucy" ) ) ), 146 )
+ def testLegacySearchUsersExplicitPagination( self ):
+ users = self.g.legacy_search_users( "Lucy" )
+ self.assertEqual( [ u.login for u in users.get_page( 1 ) ], [ "lucievh", "lucyim", "Lucief", "RevolverUpstairs", "seriousprogramming", "reicul", "davincidubai", "LucianaNascimentodoPrado", "lucia-huenchunao", "kraji20", "Lucywolo", "Luciel", "sunnysummer", "elush", "oprealuci", "Flika", "lsher", "datadrivenjournalism", "nill2020", "doobi", "lucilu", "deldeldel", "lucianacocca", "lucyli-sfdc", "lucysatchell", "UBM", "kolousek", "lucyzhang", "lmegia", "luisolivo", "Lucyzhen", "Luhzinha", "beautifly", "lucybm96", "BuonocoreL", "lucywilliams", "ZxOxZ", "Motwinb", "johnlucy", "Aquanimation", "alaltaieri", "lucylin", "lucychambers", "JuanSesma", "cdwwebware", "ZachWills" ] )
+
def testLegacySearchUserByEmail( self ):
user = self.g.legacy_search_user_by_email( "vincent@vincent-jacques.net" )
self.assertEqual( user.login, "jacquev6" )
View
12 test/PaginatedList.py
@@ -21,6 +21,12 @@ def setUp( self ):
def testIteration( self ):
self.assertEqual( len( list( self.list ) ), 333 )
+ def testSeveralIterations( self ):
+ self.assertEqual( len( list( self.list ) ), 333 )
+ self.assertEqual( len( list( self.list ) ), 333 )
+ self.assertEqual( len( list( self.list ) ), 333 )
+ self.assertEqual( len( list( self.list ) ), 333 )
+
def testIntIndexingInFirstPage( self ):
self.assertEqual( self.list[ 0 ].id, 4772349 )
self.assertEqual( self.list[ 24 ].id, 4286936 )
@@ -29,6 +35,12 @@ def testIntIndexingInThirdPage( self ):
self.assertEqual( self.list[ 50 ].id, 3911629 )
self.assertEqual( self.list[ 74 ].id, 3605277 )
+ def testGetFirstPage( self ):
+ self.assertListKeyEqual( self.list.get_page( 0 ), lambda i: i.id, [ 4772349, 4767675, 4758608, 4700182, 4662873, 4608132, 4604661, 4588997, 4557803, 4554058, 4539985, 4507572, 4507492, 4507416, 4447561, 4406584, 4384548, 4383465, 4373361, 4373201, 4370619, 4356530, 4352401, 4317009, 4286936 ] )
+
+ def testGetThirdPage( self ):
+ self.assertListKeyEqual( self.list.get_page( 2 ), lambda i: i.id, [ 3911629, 3911537, 3910580, 3910555, 3910549, 3897090, 3883598, 3856005, 3850655, 3825582, 3813852, 3812318, 3812275, 3807459, 3799872, 3799653, 3795495, 3754055, 3710293, 3662214, 3647640, 3631618, 3627067, 3614231, 3605277 ] )
+
def testIntIndexingAfterIteration( self ):
self.assertEqual( len( list( self.list ) ), 333 )
self.assertEqual( self.list[ 11 ].id, 4507572 )
View
5 test/ReplayData/Github.testLegacySearchReposExplicitPagination.txt
@@ -0,0 +1,5 @@
+https GET api.github.com None /legacy/repos/search/python?start_page=5 {'Authorization': 'Basic login_and_password_removed'} null
+200
+[('status', '200 OK'), ('x-ratelimit-remaining', '4999'), ('x-github-media-type', 'github.beta; format=json'), ('x-content-type-options', 'nosniff'), ('x-ratelimit-limit', '5000'), ('content-length', '40758'), ('server', 'nginx'), ('connection', 'keep-alive'), ('etag', '"55a485e08fb00f1ed4304534fbbf0cb0"'), ('cache-control', 'max-age=0, private, must-revalidate'), ('date', 'Tue, 11 Sep 2012 21:27:18 GMT'), ('content-type', 'application/json; charset=utf-8')]
+{"repositories":[{"type":"repo","forks":183,"owner":"kriswallsmith","pushed":"2012-09-07T10:40:33-07:00","username":"kriswallsmith","description":"Asset Management for PHP","created_at":"2011-01-10T09:47:13-08:00","watchers":1171,"followers":1171,"fork":false,"size":752,"created":"2011-01-10T09:47:13-08:00","name":"assetic","private":false,"pushed_at":"2012-09-07T10:40:33-07:00","language":"PHP"},{"type":"repo","forks":28,"owner":"Vizzuality","pushed":"2012-09-11T13:59:46-07:00","username":"Vizzuality","description":"Geospatial database for the cloud","created_at":"2011-01-12T07:25:41-08:00","watchers":238,"followers":238,"fork":false,"size":352,"created":"2011-01-12T07:25:41-08:00","name":"cartodb","private":false,"pushed_at":"2012-09-11T13:59:46-07:00","language":"JavaScript"},{"type":"repo","forks":73,"owner":"sebastien","pushed":"2012-09-11T12:10:16-07:00","username":"sebastien","description":"Chef-like functionality for Fabric","created_at":"2011-02-28T12:26:37-08:00","watchers":515,"followers":515,"fork":false,"size":236,"created":"2011-02-28T12:26:37-08:00","name":"cuisine","private":false,"pushed_at":"2012-09-11T12:10:16-07:00","language":"Python"},{"type":"repo","forks":26,"owner":"dound","pushed":"2011-12-19T12:52:24-08:00","username":"dound","description":"Fast, lightweight Sessions middleware for Google App Engine (secure cookies, memcache, or datastore)","created_at":"2010-04-07T02:30:31-07:00","watchers":231,"followers":231,"fork":false,"size":272,"created":"2010-04-07T02:30:31-07:00","name":"gae-sessions","private":false,"pushed_at":"2011-12-19T12:52:24-08:00","language":"Python"},{"type":"repo","forks":2,"owner":"geoalchemy","pushed":"2012-09-11T10:16:06-07:00","username":"geoalchemy","description":"GeoAlchemy 2","created_at":"2012-09-01T03:00:24-07:00","watchers":2,"followers":2,"fork":false,"size":228,"created":"2012-09-01T03:00:24-07:00","name":"geoalchemy2","private":false,"pushed_at":"2012-09-11T10:16:06-07:00","language":"Python"},{"type":"repo","forks":0,"owner":"SimonSapin","pushed":"2012-09-11T12:15:38-07:00","username":"SimonSapin","description":"Data Access Library","created_at":"2011-07-03T10:32:42-07:00","watchers":2,"followers":2,"fork":true,"size":232,"created":"2011-07-03T10:32:42-07:00","name":"Multicorn","private":false,"pushed_at":"2012-09-11T12:15:38-07:00","language":"Python"},{"type":"repo","forks":0,"owner":"JeanFred","pushed":"2012-09-11T13:08:53-07:00","username":"JeanFred","description":"A WmFr timeline","created_at":"2012-08-07T12:38:19-07:00","watchers":0,"followers":0,"fork":false,"size":336,"created":"2012-08-07T12:38:19-07:00","name":"wmfr-timeline","private":false,"pushed_at":"2012-09-11T13:08:53-07:00","language":"Python"},{"type":"repo","forks":12,"owner":"sripathikrishnan","pushed":"2012-08-02T08:16:15-07:00","username":"sripathikrishnan","description":"Parse Redis dump.rdb files, Analyze Memory, and Export Data to JSON","created_at":"2012-03-10T03:09:12-08:00","watchers":108,"followers":108,"fork":false,"size":132,"created":"2012-03-10T03:09:12-08:00","name":"redis-rdb-tools","private":false,"pushed_at":"2012-08-02T08:16:15-07:00","language":"Python"},{"type":"repo","forks":1,"owner":"Ilastik","pushed":"2012-09-11T10:02:43-07:00","username":"Ilastik","description":"ilastik-shell, applets, and workflows to string them together.","created_at":"2012-05-08T08:59:36-07:00","watchers":1,"followers":1,"fork":false,"size":296,"created":"2012-05-08T08:59:36-07:00","name":"applet-workflows","private":false,"pushed_at":"2012-09-11T10:02:43-07:00","language":"Python"},{"type":"repo","forks":0,"owner":"agoebel","pushed":"2012-09-11T10:19:08-07:00","username":"agoebel","description":"a micro command line tool that posts delayed tweets (like Buffer)","created_at":"2012-09-11T10:18:41-07:00","watchers":0,"followers":0,"fork":false,"size":92,"created":"2012-09-11T10:18:41-07:00","name":"TweetBuff","private":false,"pushed_at":"2012-09-11T10:19:08-07:00","language":"Python"},{"type":"repo","forks":77,"owner":"groovy","pushed":"2012-09-11T10:24:22-07:00","username":"groovy","description":"Groovy language Git repository","created_at":"2011-09-19T00:41:42-07:00","watchers":227,"followers":227,"fork":false,"size":928,"created":"2011-09-19T00:41:42-07:00","name":"groovy-core","private":false,"pushed_at":"2012-09-11T10:24:22-07:00","language":"Java"},{"type":"repo","forks":0,"owner":"RazvanB","pushed":"2012-09-11T10:34:54-07:00","username":"RazvanB","description":"","created_at":"2012-09-06T10:53:50-07:00","watchers":0,"followers":0,"fork":false,"size":220,"created":"2012-09-06T10:53:50-07:00","name":"StarTrekGame","private":false,"pushed_at":"2012-09-11T10:34:54-07:00","language":"Python"},{"type":"repo","forks":0,"owner":"Ugrt","pushed":"2012-09-11T11:19:36-07:00","username":"Ugrt","description":"Un nuevo repositorio","created_at":"2012-09-11T11:12:55-07:00","watchers":0,"followers":0,"fork":false,"size":92,"created":"2012-09-11T11:12:55-07:00","name":"Nuevo","private":false,"pushed_at":"2012-09-11T11:19:36-07:00","language":"Python"},{"type":"repo","forks":2,"owner":"andrewfiorillo","pushed":"2012-08-02T14:07:38-07:00","username":"andrewfiorillo","description":"Cupid color scheme for Sublime Text 2 and Textmate","created_at":"2012-05-29T07:05:33-07:00","watchers":3,"followers":3,"fork":false,"size":136,"created":"2012-05-29T07:05:33-07:00","name":"Cupid","private":false,"pushed_at":"2012-08-02T14:07:38-07:00","language":null},{"type":"repo","forks":25,"owner":"WindowsAzure","pushed":"2012-08-30T14:23:42-07:00","username":"WindowsAzure","description":"","created_at":"2012-03-02T08:35:36-08:00","watchers":175,"followers":175,"fork":false,"size":168,"created":"2012-03-02T08:35:36-08:00","name":"node-sqlserver","private":false,"pushed_at":"2012-08-30T14:23:42-07:00","language":"C++"},{"type":"repo","forks":6,"owner":"danfolkes","pushed":"2012-09-09T18:39:17-07:00","username":"danfolkes","description":"This will convert a magnet link into a .torrent file","created_at":"2012-04-19T07:31:02-07:00","watchers":17,"followers":17,"fork":false,"size":128,"created":"2012-04-19T07:31:02-07:00","name":"Magnet2Torrent","private":false,"pushed_at":"2012-09-09T18:39:17-07:00","language":"Python"},{"type":"repo","forks":18,"owner":"mattt","pushed":"2012-09-06T08:06:47-07:00","username":"mattt","description":"Remote configuration for iOS","created_at":"2012-08-31T16:13:59-07:00","watchers":308,"followers":308,"fork":false,"size":136,"created":"2012-08-31T16:13:59-07:00","name":"GroundControl","private":false,"pushed_at":"2012-09-06T08:06:47-07:00","language":"Objective-C"},{"type":"repo","forks":5,"owner":"dcramer","pushed":"2012-08-16T12:45:29-07:00","username":"dcramer","description":"","created_at":"2012-02-06T13:39:47-08:00","watchers":33,"followers":33,"fork":false,"size":132,"created":"2012-02-06T13:39:47-08:00","name":"mock-django","private":false,"pushed_at":"2012-08-16T12:45:29-07:00","language":"Python"},{"type":"repo","forks":16,"owner":"ciembor","pushed":"2012-09-07T10:18:30-07:00","username":"ciembor","description":"Terminal Color Scheme Designer","created_at":"2012-08-20T11:36:25-07:00","watchers":164,"followers":164,"fork":false,"size":208,"created":"2012-08-20T11:36:25-07:00","name":"4bit","private":false,"pushed_at":"2012-09-07T10:18:30-07:00","language":"JavaScript"},{"type":"repo","forks":0,"owner":"hexsprite","pushed":"2012-09-11T12:12:32-07:00","username":"hexsprite","description":"","created_at":"2012-09-11T12:05:15-07:00","watchers":0,"followers":0,"fork":true,"size":112,"created":"2012-09-11T12:05:15-07:00","name":"mock-django","private":false,"pushed_at":"2012-09-11T12:12:32-07:00","language":"Python"},{"type":"repo","forks":39,"owner":"gcollazo","pushed":"2012-08-08T09:06:13-07:00","username":"gcollazo","description":"Deploy django apps to Amazon EC2 with ONE command","created_at":"2011-06-26T13:27:07-07:00","watchers":383,"followers":383,"fork":false,"size":136,"created":"2011-06-26T13:27:07-07:00","name":"Fabulous","private":false,"pushed_at":"2012-08-08T09:06:13-07:00","language":"Python"},{"type":"repo","forks":78,"owner":"LaurentGomila","pushed":"2012-09-01T14:23:07-07:00","username":"LaurentGomila","description":"Simple and Fast Multimedia Library","created_at":"2011-03-25T01:05:25-07:00","watchers":637,"followers":637,"fork":false,"size":796,"created":"2011-03-25T01:05:25-07:00","name":"SFML","private":false,"pushed_at":"2012-09-01T14:23:07-07:00","language":"C"},{"type":"repo","forks":0,"owner":"fabiocerqueira","pushed":"2012-09-11T12:39:14-07:00","username":"fabiocerqueira","description":"Página pessoal: http://cerqueira.me","created_at":"2012-09-11T12:38:06-07:00","watchers":0,"followers":0,"fork":false,"size":316,"created":"2012-09-11T12:38:06-07:00","name":"pydicas","private":false,"pushed_at":"2012-09-11T12:39:14-07:00","language":"JavaScript"},{"type":"repo","forks":139,"owner":"AdamAtomic","pushed":"2011-10-16T12:30:21-07:00","username":"AdamAtomic","description":"flixel is a free Actionscript (Flash) library that I distilled from a variety of Flash games that I've worked on over the last couple years, including Gravity Hook, Fathom and Canabalt. It's primary function is to provide some useful base classes that you can extend to make your own game objects.","created_at":"2009-10-18T16:14:40-07:00","watchers":916,"followers":916,"fork":false,"size":284,"created":"2009-10-18T16:14:40-07:00","name":"flixel","private":false,"pushed_at":"2011-10-16T12:30:21-07:00","language":"ActionScript"},{"type":"repo","forks":0,"owner":"joehewitt","pushed":"2012-09-11T01:08:28-07:00","username":"joehewitt","description":"It's a programming language.","created_at":"2012-08-04T23:56:03-07:00","watchers":19,"followers":19,"fork":false,"size":3376,"created":"2012-08-04T23:56:03-07:00","name":"up","private":false,"pushed_at":"2012-09-11T01:08:28-07:00","language":"C"},{"type":"repo","forks":71,"owner":"zedshaw","pushed":"2012-09-01T11:24:16-07:00","username":"zedshaw","description":"The Mongrel2 Web Server Project","created_at":"2011-05-21T10:04:11-07:00","watchers":760,"followers":760,"fork":false,"size":264,"created":"2011-05-21T10:04:11-07:00","name":"mongrel2","private":false,"pushed_at":"2012-09-01T11:24:16-07:00","language":"C"},{"type":"repo","forks":0,"owner":"fabriceleal","pushed":"2012-09-11T13:43:09-07:00","username":"fabriceleal","description":"A static page server in node.js","created_at":"2012-09-10T14:38:34-07:00","watchers":1,"followers":1,"fork":false,"size":120,"created":"2012-09-10T14:38:34-07:00","name":"SimpleHTTPServerJs","private":false,"pushed_at":"2012-09-11T13:43:09-07:00","language":"JavaScript"},{"type":"repo","forks":0,"owner":"djrahl","pushed":"2012-09-11T13:48:10-07:00","username":"djrahl","description":"a crpg in the spirit of ultima v","created_at":"2012-09-11T13:38:24-07:00","watchers":0,"followers":0,"fork":false,"size":92,"created":"2012-09-11T13:38:24-07:00","name":"ultimos","private":false,"pushed_at":"2012-09-11T13:48:10-07:00","language":null},{"type":"repo","forks":45,"owner":"ArchipelProject","pushed":"2012-09-11T13:51:51-07:00","username":"ArchipelProject","description":"XMPP Based Orchestrator","created_at":"2010-09-25T08:03:52-07:00","watchers":298,"followers":298,"fork":false,"size":416,"created":"2010-09-25T08:03:52-07:00","name":"Archipel","private":false,"pushed_at":"2012-09-11T13:51:51-07:00","language":"Objective-J"},{"type":"repo","forks":32,"owner":"revolunet","pushed":"2012-08-27T09:22:58-07:00","username":"revolunet","description":"Open source javascript books compilation","created_at":"2012-07-31T01:03:56-07:00","watchers":153,"followers":153,"fork":false,"size":184,"created":"2012-07-31T01:03:56-07:00","name":"JSbooks","private":false,"pushed_at":"2012-08-27T09:22:58-07:00","language":"JavaScript"},{"type":"repo","forks":345,"owner":"openstack","pushed":"2012-09-11T14:17:33-07:00","username":"openstack","description":"OpenStack Compute (Nova)","created_at":"2010-07-21T19:04:27-07:00","watchers":630,"followers":630,"fork":false,"size":7912,"created":"2010-07-21T19:04:27-07:00","name":"nova","private":false,"pushed_at":"2012-09-11T14:17:33-07:00","language":"Python"},{"type":"repo","forks":9,"owner":"nodebox","pushed":"2012-09-11T14:18:01-07:00","username":"nodebox","description":"Interactive, hackable graphic design application ","created_at":"2009-02-10T08:28:47-08:00","watchers":160,"followers":160,"fork":false,"size":452568,"created":"2009-02-10T08:28:47-08:00","name":"nodebox","private":false,"pushed_at":"2012-09-11T14:18:01-07:00","language":"Java"},{"type":"repo","forks":24,"owner":"bitly","pushed":"2012-09-11T14:24:12-07:00","username":"bitly","description":"a family of libraries and daemons for building scalable web infrastructure","created_at":"2010-12-16T14:13:56-08:00","watchers":143,"followers":143,"fork":false,"size":193,"created":"2010-12-16T14:13:56-08:00","name":"simplehttp","private":false,"pushed_at":"2012-09-11T14:24:12-07:00","language":"C"},{"type":"repo","forks":23,"owner":"bitly","pushed":"2012-09-04T10:07:19-07:00","username":"bitly","description":"scaling, counting, bloom filter library","created_at":"2012-07-25T11:41:03-07:00","watchers":326,"followers":326,"fork":false,"size":356,"created":"2012-07-25T11:41:03-07:00","name":"dablooms","private":false,"pushed_at":"2012-09-04T10:07:19-07:00","language":"C"},{"type":"repo","forks":362,"owner":"altercation","pushed":"2012-08-26T22:50:52-07:00","username":"altercation","description":"precision color scheme for multiple applications (terminal, vim, etc.) with both dark/light modes","created_at":"2011-02-17T21:18:27-08:00","watchers":2918,"followers":2918,"fork":false,"size":388,"created":"2011-02-17T21:18:27-08:00","name":"solarized","private":false,"pushed_at":"2012-08-26T22:50:52-07:00","language":"Perl"},{"type":"repo","forks":132,"owner":"adamzap","pushed":"2012-09-06T21:24:25-07:00","username":"adamzap","description":"Generate a slideshow using the slides that power the html5-slides presentation","created_at":"2010-05-11T21:34:16-07:00","watchers":693,"followers":693,"fork":false,"size":176,"created":"2010-05-11T21:34:16-07:00","name":"landslide","private":false,"pushed_at":"2012-09-06T21:24:25-07:00","language":"Python"},{"type":"repo","forks":0,"owner":"i2bizpl","pushed":"2012-09-05T21:11:49-07:00","username":"i2bizpl","description":"File Upload widget with multiple file selection, drag&drop support, progress bars and preview images for jQuery. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.","created_at":"2012-09-11T10:22:38-07:00","watchers":0,"followers":0,"fork":true,"size":316,"created":"2012-09-11T10:22:38-07:00","name":"jQuery-File-Upload","private":false,"pushed_at":"2012-09-05T21:11:49-07:00","language":"JavaScript"},{"type":"repo","forks":3,"owner":"swhitley","pushed":"2012-05-18T21:06:33-07:00","username":"swhitley","description":"File Upload widget with multiple file selection, drag&drop support, progress bars and preview images for jQuery. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.","created_at":"2012-05-18T15:15:11-07:00","watchers":5,"followers":5,"fork":true,"size":116,"created":"2012-05-18T15:15:11-07:00","name":"jQuery-File-Upload","private":false,"pushed_at":"2012-05-18T21:06:33-07:00","language":"JavaScript"},{"type":"repo","forks":3,"owner":"timabell","pushed":"2012-03-21T09:32:35-07:00","username":"timabell","description":"File Upload widget with multiple file selection, drag&drop support, progress bars and preview images for jQuery. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.","created_at":"2012-03-21T09:12:48-07:00","watchers":7,"followers":7,"fork":true,"size":612,"created":"2012-03-21T09:12:48-07:00","name":"jQuery-File-Upload","private":false,"pushed_at":"2012-03-21T09:32:35-07:00","language":"JavaScript"},{"type":"repo","forks":0,"owner":"MisterY","pushed":"2012-09-11T14:11:50-07:00","username":"MisterY","description":"Clipperz Community Edition is a web-based password manager. It allows you to host on your own server a web service identical to the well-known Clipperz online password manager. It supports multiple backends (PHP/MySQL, Python/AppEngine, …) and you can contribute your own. Local encryption within the browser guarantees that no one except you can read your data.","created_at":"2012-09-08T11:10:24-07:00","watchers":0,"followers":0,"fork":true,"size":156,"created":"2012-09-08T11:10:24-07:00","name":"password-manager","private":false,"pushed_at":"2012-09-11T14:11:50-07:00","language":"JavaScript"},{"type":"repo","forks":7,"owner":"spesmilo","pushed":"2012-09-11T12:02:13-07:00","username":"spesmilo","description":"Electrum; Bitcoin thin client","created_at":"2012-08-02T09:24:30-07:00","watchers":19,"followers":19,"fork":false,"size":552,"created":"2012-08-02T09:24:30-07:00","name":"electrum","private":false,"pushed_at":"2012-09-11T12:02:13-07:00","language":"Python"},{"type":"repo","forks":8,"owner":"aritter","pushed":"2012-06-28T20:57:20-07:00","username":"aritter","description":"UW Twitter NLP Tools","created_at":"2011-07-16T13:24:35-07:00","watchers":54,"followers":54,"fork":false,"size":1272,"created":"2011-07-16T13:24:35-07:00","name":"twitter_nlp","private":false,"pushed_at":"2012-06-28T20:57:20-07:00","language":"Java"},{"type":"repo","forks":12,"owner":"af","pushed":"2012-05-06T20:38:22-07:00","username":"af","description":"Makes it easy for Django backends to talk to Backbone.js.","created_at":"2011-11-26T13:33:53-08:00","watchers":122,"followers":122,"fork":false,"size":128,"created":"2011-11-26T13:33:53-08:00","name":"djangbone","private":false,"pushed_at":"2012-05-06T20:38:22-07:00","language":"Python"},{"type":"repo","forks":0,"owner":"vchahun","pushed":"2012-09-11T10:47:11-07:00","username":"vchahun","description":"Cython XFST bindings","created_at":"2012-09-11T10:46:18-07:00","watchers":0,"followers":0,"fork":false,"size":112,"created":"2012-09-11T10:46:18-07:00","name":"pyxfst","private":false,"pushed_at":"2012-09-11T10:47:11-07:00","language":"C"},{"type":"repo","forks":17,"owner":"TooTallNate","pushed":"2012-09-07T11:08:32-07:00","username":"TooTallNate","description":"Node.js native addon build tool","created_at":"2012-02-02T21:50:50-08:00","watchers":170,"followers":170,"fork":false,"size":1184,"created":"2012-02-02T21:50:50-08:00","name":"node-gyp","private":false,"pushed_at":"2012-09-07T11:08:32-07:00","language":"Python"},{"type":"repo","forks":63,"owner":"clintbellanger","pushed":"2012-09-11T11:27:46-07:00","username":"clintbellanger","description":"Free Libre Action Roleplaying Engine","created_at":"2011-06-03T19:53:27-07:00","watchers":178,"followers":178,"fork":false,"size":258771,"created":"2011-06-03T19:53:27-07:00","name":"flare","private":false,"pushed_at":"2012-09-11T11:27:46-07:00","language":"C++"},{"type":"repo","forks":21,"owner":"whit537","pushed":"2012-09-11T11:48:51-07:00","username":"whit537","description":"Gittip is a personal funding platform.","created_at":"2012-06-01T09:01:02-07:00","watchers":148,"followers":148,"fork":false,"size":764,"created":"2012-06-01T09:01:02-07:00","name":"www.gittip.com","private":false,"pushed_at":"2012-09-11T11:48:51-07:00","language":"Python"},{"type":"repo","forks":57,"owner":"wymeditor","pushed":"2012-08-24T07:33:42-07:00","username":"wymeditor","description":"Pure js cross-browser WYSIWYM editor with a focus on the clean separation of content and styling.","created_at":"2010-01-22T02:50:59-08:00","watchers":336,"followers":336,"fork":false,"size":1464,"created":"2010-01-22T02:50:59-08:00","name":"wymeditor","private":false,"pushed_at":"2012-08-24T07:33:42-07:00","language":"JavaScript"},{"type":"repo","forks":1,"owner":"Kokothekoala","pushed":"2012-09-11T13:10:34-07:00","username":"Kokothekoala","description":"","created_at":"2012-06-29T01:30:02-07:00","watchers":1,"followers":1,"fork":false,"size":2452,"created":"2012-06-29T01:30:02-07:00","name":"Kokobox","private":false,"pushed_at":"2012-09-11T13:10:34-07:00","language":"Python"},{"type":"repo","forks":0,"owner":"practo","pushed":"2012-08-01T15:35:10-07:00","username":"practo","description":"MyCQ is a simple website written in Flask to give MCQ test","created_at":"2012-07-29T08:51:31-07:00","watchers":2,"followers":2,"fork":false,"size":240,"created":"2012-07-29T08:51:31-07:00","name":"MyCQ","private":false,"pushed_at":"2012-08-01T15:35:10-07:00","language":"Python"},{"type":"repo","forks":0,"owner":"mhsundstrom","pushed":"2012-09-11T13:14:23-07:00","username":"mhsundstrom","description":"data analysis of race and workout runwalks","created_at":"2012-08-03T09:33:43-07:00","watchers":1,"followers":1,"fork":false,"size":272,"created":"2012-08-03T09:33:43-07:00","name":"runwalk","private":false,"pushed_at":"2012-09-11T13:14:23-07:00","language":"JavaScript"},{"type":"repo","forks":7,"owner":"arc90","pushed":"2012-04-23T07:38:20-07:00","username":"arc90","description":"A command-line tool that helps you clean up Git branches that have been merged into master.","created_at":"2012-03-16T06:58:07-07:00","watchers":114,"followers":114,"fork":false,"size":172,"created":"2012-03-16T06:58:07-07:00","name":"git-sweep","private":false,"pushed_at":"2012-04-23T07:38:20-07:00","language":"Python"},{"type":"repo","forks":0,"owner":"aterrel","pushed":"2012-09-11T14:07:51-07:00","username":"aterrel","description":"","created_at":"2012-09-05T12:44:32-07:00","watchers":1,"followers":1,"fork":false,"size":1712,"created":"2012-09-05T12:44:32-07:00","name":"HPCPythonSC2012","private":false,"pushed_at":"2012-09-11T14:07:51-07:00","language":null},{"type":"repo","forks":73,"owner":"vmg","pushed":"2012-08-01T16:27:07-07:00","username":"vmg","description":"Standards compliant, fast, secure markdown processing library in C","created_at":"2011-04-15T01:38:13-07:00","watchers":566,"followers":566,"fork":false,"size":192,"created":"2011-04-15T01:38:13-07:00","name":"sundown","private":false,"pushed_at":"2012-08-01T16:27:07-07:00","language":"C"},{"type":"repo","forks":59,"owner":"Instagram","pushed":"2012-06-13T10:47:46-07:00","username":"Instagram","description":"","created_at":"2012-02-17T00:21:51-08:00","watchers":613,"followers":613,"fork":false,"size":136,"created":"2012-02-17T00:21:51-08:00","name":"node2dm","private":false,"pushed_at":"2012-06-13T10:47:46-07:00","language":"JavaScript"},{"type":"repo","forks":1,"owner":"MeirKriheli","pushed":"2012-09-11T10:34:46-07:00","username":"MeirKriheli","description":"Multilingual static site and blog generator","created_at":"2011-04-27T11:47:17-07:00","watchers":1,"followers":1,"fork":false,"size":324,"created":"2011-04-27T11:47:17-07:00","name":"statirator","private":false,"pushed_at":"2012-09-11T10:34:46-07:00","language":"Python"},{"type":"repo","forks":0,"owner":"orzubalsky","pushed":"2012-09-11T11:12:18-07:00","username":"orzubalsky","description":"","created_at":"2012-08-22T07:24:46-07:00","watchers":0,"followers":0,"fork":false,"size":7176,"created":"2012-08-22T07:24:46-07:00","name":"fantastic-futures","private":false,"pushed_at":"2012-09-11T11:12:18-07:00","language":"JavaScript"},{"type":"repo","forks":1,"owner":"blahed","pushed":"2012-09-04T15:52:24-07:00","username":"blahed","description":"","created_at":"2012-08-30T11:56:14-07:00","watchers":138,"followers":138,"fork":false,"size":624,"created":"2012-08-30T11:56:14-07:00","name":"chainsaw","private":false,"pushed_at":"2012-09-04T15:52:24-07:00","language":"Ruby"},{"type":"repo","forks":1,"owner":"lucasmcastro","pushed":"2012-02-11T12:54:37-08:00","username":"lucasmcastro","description":"Gerenciador Tarefas IT Cursos","created_at":"2012-02-04T06:05:58-08:00","watchers":1,"followers":1,"fork":false,"size":136,"created":"2012-02-04T06:05:58-08:00","name":"itcursos-gerenciador-tarefas","private":false,"pushed_at":"2012-02-11T12:54:37-08:00","language":"Python"},{"type":"repo","forks":25,"owner":"TideSDK","pushed":"2012-09-07T21:49:37-07:00","username":"TideSDK","description":"Create multi-platform desktop apps with HTML5, CSS3 and JavaScript. TideSDK formerly known as Titanium Desktop is the best way to create beautiful, unique desktop apps using your web development skills.","created_at":"2012-03-06T05:53:47-08:00","watchers":174,"followers":174,"fork":true,"size":155104,"created":"2012-03-06T05:53:47-08:00","name":"TideSDK","private":false,"pushed_at":"2012-09-07T21:49:37-07:00","language":"C++"},{"type":"repo","forks":1,"owner":"KpaBap","pushed":"2012-09-11T12:18:52-07:00","username":"KpaBap","description":"Simple IRC Channel bot","created_at":"2012-06-21T09:20:27-07:00","watchers":3,"followers":3,"fork":true,"size":456,"created":"2012-06-21T09:20:27-07:00","name":"genmaybot","private":false,"pushed_at":"2012-09-11T12:18:52-07:00","language":"Python"},{"type":"repo","forks":83,"owner":"milkypostman","pushed":"2012-09-10T13:33:00-07:00","username":"milkypostman","description":"Scripts for building Emacs packages from Version Control","created_at":"2011-10-04T22:50:47-07:00","watchers":130,"followers":130,"fork":false,"size":564,"created":"2011-10-04T22:50:47-07:00","name":"melpa","private":false,"pushed_at":"2012-09-10T13:33:00-07:00","language":"JavaScript"},{"type":"repo","forks":0,"owner":"mjcuva","pushed":"2012-09-11T12:43:02-07:00","username":"mjcuva","description":null,"created_at":"2012-08-23T13:21:24-07:00","watchers":0,"followers":0,"fork":false,"size":1996,"created":"2012-08-23T13:21:24-07:00","name":"ConnectedWire","private":false,"pushed_at":"2012-09-11T12:43:02-07:00","language":"Python"},{"type":"repo","forks":13,"owner":"mailru","pushed":"2012-09-11T13:07:39-07:00","username":"mailru","description":"efficient in-memory storage","created_at":"2010-09-15T00:59:26-07:00","watchers":122,"followers":122,"fork":false,"size":560,"created":"2010-09-15T00:59:26-07:00","name":"tarantool","private":false,"pushed_at":"2012-09-11T13:07:39-07:00","language":"C"},{"type":"repo","forks":0,"owner":"agodbehere","pushed":"2012-09-11T13:20:51-07:00","username":"agodbehere","description":"experimental db alpha internal","created_at":"2012-09-10T12:33:32-07:00","watchers":0,"followers":0,"fork":false,"size":308,"created":"2012-09-10T12:33:32-07:00","name":"anserindicus_sn","private":false,"pushed_at":"2012-09-11T13:20:51-07:00","language":"Python"},{"type":"repo","forks":61,"owner":"luvit","pushed":"2012-09-11T13:24:05-07:00","username":"luvit","description":"Lua + libUV + jIT = pure awesomesauce","created_at":"2011-09-10T15:54:00-07:00","watchers":742,"followers":742,"fork":false,"size":936,"created":"2011-09-10T15:54:00-07:00","name":"luvit","private":false,"pushed_at":"2012-09-11T13:24:05-07:00","language":"C"},{"type":"repo","forks":131,"owner":"overviewer","pushed":"2012-09-11T13:42:15-07:00","username":"overviewer","description":"Render high-resolution maps of a Minecraft world with a Google Maps powered interface","created_at":"2010-08-28T14:44:16-07:00","watchers":646,"followers":646,"fork":false,"size":45878,"created":"2010-08-28T14:44:16-07:00","name":"Minecraft-Overviewer","private":false,"pushed_at":"2012-09-11T13:42:15-07:00","language":"Python"},{"type":"repo","forks":117,"owner":"somerandomdude","pushed":"2012-07-10T14:04:49-07:00","username":"somerandomdude","description":"A minimal set of icons in raster, vector and font formats — free for public use.","created_at":"2011-09-21T19:11:09-07:00","watchers":932,"followers":932,"fork":false,"size":10490,"created":"2011-09-21T19:11:09-07:00","name":"Iconic","private":false,"pushed_at":"2012-07-10T14:04:49-07:00","language":"Python"},{"type":"repo","forks":0,"owner":"cihann","pushed":"2012-09-11T14:23:44-07:00","username":"cihann","description":"","created_at":"2012-05-20T11:15:16-07:00","watchers":1,"followers":1,"fork":true,"size":132,"created":"2012-05-20T11:15:16-07:00","name":"pyist.net&q