Repository: PyGithub/PyGithub

Issue:
Search repo issue by label without `get_label`
In order to search a repo's issues by label, you first need to fetch the label, then perform the search. This means we're doing an extra HTTP request (and using an extra API usage) just to search issues.
I am working on integration with a repo where I know the label exists. Either way, this is irrelevant as GitHub will return no results for a label that doesn't exist.

What I propose is to allow searching issues by the label strings removing the need for an extra API request. This means that PyGithub has the same behaviour for handling labels in `Repository.get_issues` as `Repository.create_issue`


Discussion:

Resolving patch:
diff --git a/github/Issue.py b/github/Issue.py
--- a/github/Issue.py
+++ b/github/Issue.py
@@ -364,7 +364,7 @@ def edit(
         :param title: string
         :param body: string
         :param assignee: string or :class:`github.NamedUser.NamedUser` or None
-        :param assignees: list (of string or :class:`github.NamedUser.NamedUser`)
+        :param assignees: list of string or :class:`github.NamedUser.NamedUser`
         :param state: string
         :param milestone: :class:`github.Milestone.Milestone` or None
         :param labels: list of string
diff --git a/github/Repository.py b/github/Repository.py
--- a/github/Repository.py
+++ b/github/Repository.py
@@ -1120,7 +1120,7 @@ def create_issue(
         :param title: string
         :param body: string
         :param assignee: string or :class:`github.NamedUser.NamedUser`
-        :param assignees: list (of string or :class:`github.NamedUser.NamedUser`)
+        :param assignees: list of string or :class:`github.NamedUser.NamedUser`
         :param milestone: :class:`github.Milestone.Milestone`
         :param labels: list of :class:`github.Label.Label`
         :rtype: :class:`github.Issue.Issue`
@@ -2192,7 +2192,7 @@ def get_issues(
         :param state: string. `open`, `closed`, or `all`. If this is not set the GitHub API default behavior will be used. At the moment this is to return only open issues. This might change anytime on GitHub API side and it could be clever to explicitly specify the state value.
         :param assignee: string or :class:`github.NamedUser.NamedUser` or "none" or "*"
         :param mentioned: :class:`github.NamedUser.NamedUser`
-        :param labels: list of :class:`github.Label.Label`
+        :param labels: list of string or :class:`github.Label.Label`
         :param sort: string
         :param direction: string
         :param since: datetime.datetime
@@ -2215,7 +2215,8 @@ def get_issues(
             mentioned, github.NamedUser.NamedUser
         ), mentioned
         assert labels is github.GithubObject.NotSet or all(
-            isinstance(element, github.Label.Label) for element in labels
+            isinstance(element, github.Label.Label) or isinstance(element, str)
+            for element in labels
         ), labels
         assert sort is github.GithubObject.NotSet or isinstance(sort, str), sort
         assert direction is github.GithubObject.NotSet or isinstance(
@@ -2245,7 +2246,12 @@ def get_issues(
         if mentioned is not github.GithubObject.NotSet:
             url_parameters["mentioned"] = mentioned._identity
         if labels is not github.GithubObject.NotSet:
-            url_parameters["labels"] = ",".join(label.name for label in labels)
+            url_parameters["labels"] = ",".join(
+                [
+                    label.name if isinstance(label, github.Label.Label) else label
+                    for label in labels
+                ]
+            )
         if sort is not github.GithubObject.NotSet:
             url_parameters["sort"] = sort
         if direction is not github.GithubObject.NotSet:


Test patch:
diff --git a/tests/ReplayData/Repository.testGetIssuesWithArguments.txt b/tests/ReplayData/Repository.testGetIssuesWithArguments.txt
--- a/tests/ReplayData/Repository.testGetIssuesWithArguments.txt
+++ b/tests/ReplayData/Repository.testGetIssuesWithArguments.txt
@@ -64,6 +64,17 @@ None
 [('status', '200 OK'), ('x-ratelimit-remaining', '4867'), ('content-length', '2426'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"dcab4e56d1acdb64e964e0f8669f5c19"'), ('date', 'Tue, 29 May 2012 18:39:44 GMT'), ('content-type', 'application/json; charset=utf-8')]
 [{"updated_at":"2012-05-28T14:47:02Z","body":"As the title says, `get_issues()` seems to return a max of 250 items. \nIt can't be a pagination thing I think because a page is max. 100 items long as per http://developer.github.com/v3/#pagination\n\nRepro:\n\n\tfrom github import Github\n\tg = Github()\n\ttest=g.get_user('openframeworks').get_repo('openFrameworks').get_issues()\n\tlen(test)\n\nThis repo hast 940 closed and 340 open issues.","url":"https://api.github.com/repos/jacquev6/PyGithub/issues/33","comments":4,"milestone":{"closed_issues":6,"creator":{"url":"https://api.github.com/users/jacquev6","gravatar_id":"b68de5ae38616c296fa345d2b9df2225","login":"jacquev6","avatar_url":"https://secure.gravatar.com/avatar/b68de5ae38616c296fa345d2b9df2225?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png","id":327146},"url":"https://api.github.com/repos/jacquev6/PyGithub/milestones/2","number":2,"title":"Version 1.0: coherent public interface","due_on":"2012-06-04T07:00:00Z","open_issues":13,"created_at":"2012-03-08T12:22:28Z","state":"open","description":"Heavy rewrite to have:\r\n* a fully coherent public interface\r\n* usable stack-traces in case of exception\r\n* more explicit exceptions\r\n* more readable code (for library exploration, auto-completion in IDEs, etc.)\r\n\r\nSee working branch https://github.com/jacquev6/PyGithub/tree/topic/RewriteWithGeneratedCode","id":93547},"number":33,"html_url":"https://github.com/jacquev6/PyGithub/issues/33","assignee":{"url":"https://api.github.com/users/jacquev6","gravatar_id":"b68de5ae38616c296fa345d2b9df2225","login":"jacquev6","avatar_url":"https://secure.gravatar.com/avatar/b68de5ae38616c296fa345d2b9df2225?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png","id":327146},"title":"get_issues() returns max. 250 items","labels":[{"url":"https://api.github.com/repos/jacquev6/PyGithub/labels/Bug","name":"Bug","color":"e10c02"}],"closed_at":null,"created_at":"2012-05-28T13:18:01Z","state":"open","user":{"url":"https://api.github.com/users/bilderbuchi","gravatar_id":"2aed663a62fa8bf9f7aebe603d3998bb","login":"bilderbuchi","avatar_url":"https://secure.gravatar.com/avatar/2aed663a62fa8bf9f7aebe603d3998bb?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png","id":327442},"id":4780155,"pull_request":{"patch_url":null,"diff_url":null,"html_url":null}}]
 
+https
+GET
+api.github.com
+None
+/repos/jacquev6/PyGithub/issues?labels=Bug
+{'Authorization': 'Basic login_and_password_removed', 'User-Agent': 'PyGithub/Python'}
+None
+200
+[('status', '200 OK'), ('x-ratelimit-remaining', '4867'), ('content-length', '2426'), ('server', 'nginx/1.0.13'), ('connection', 'keep-alive'), ('x-ratelimit-limit', '5000'), ('etag', '"dcab4e56d1acdb64e964e0f8669f5c19"'), ('date', 'Tue, 29 May 2012 18:39:44 GMT'), ('content-type', 'application/json; charset=utf-8')]
+[{"updated_at":"2012-05-28T14:47:02Z","body":"As the title says, `get_issues()` seems to return a max of 250 items. \nIt can't be a pagination thing I think because a page is max. 100 items long as per http://developer.github.com/v3/#pagination\n\nRepro:\n\n\tfrom github import Github\n\tg = Github()\n\ttest=g.get_user('openframeworks').get_repo('openFrameworks').get_issues()\n\tlen(test)\n\nThis repo hast 940 closed and 340 open issues.","url":"https://api.github.com/repos/jacquev6/PyGithub/issues/33","comments":4,"milestone":{"closed_issues":6,"creator":{"url":"https://api.github.com/users/jacquev6","gravatar_id":"b68de5ae38616c296fa345d2b9df2225","login":"jacquev6","avatar_url":"https://secure.gravatar.com/avatar/b68de5ae38616c296fa345d2b9df2225?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png","id":327146},"url":"https://api.github.com/repos/jacquev6/PyGithub/milestones/2","number":2,"title":"Version 1.0: coherent public interface","due_on":"2012-06-04T07:00:00Z","open_issues":13,"created_at":"2012-03-08T12:22:28Z","state":"open","description":"Heavy rewrite to have:\r\n* a fully coherent public interface\r\n* usable stack-traces in case of exception\r\n* more explicit exceptions\r\n* more readable code (for library exploration, auto-completion in IDEs, etc.)\r\n\r\nSee working branch https://github.com/jacquev6/PyGithub/tree/topic/RewriteWithGeneratedCode","id":93547},"number":33,"html_url":"https://github.com/jacquev6/PyGithub/issues/33","assignee":{"url":"https://api.github.com/users/jacquev6","gravatar_id":"b68de5ae38616c296fa345d2b9df2225","login":"jacquev6","avatar_url":"https://secure.gravatar.com/avatar/b68de5ae38616c296fa345d2b9df2225?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png","id":327146},"title":"get_issues() returns max. 250 items","labels":[{"url":"https://api.github.com/repos/jacquev6/PyGithub/labels/Bug","name":"Bug","color":"e10c02"}],"closed_at":null,"created_at":"2012-05-28T13:18:01Z","state":"open","user":{"url":"https://api.github.com/users/bilderbuchi","gravatar_id":"2aed663a62fa8bf9f7aebe603d3998bb","login":"bilderbuchi","avatar_url":"https://secure.gravatar.com/avatar/2aed663a62fa8bf9f7aebe603d3998bb?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png","id":327442},"id":4780155,"pull_request":{"patch_url":null,"diff_url":null,"html_url":null}}]
+
 https
 GET
 api.github.com
diff --git a/tests/Repository.py b/tests/Repository.py
--- a/tests/Repository.py
+++ b/tests/Repository.py
@@ -792,6 +792,9 @@ def testGetIssuesWithArguments(self):
         self.assertListKeyEqual(
             self.repo.get_issues(labels=[bug]), lambda i: i.id, [4780155]
         )
+        self.assertListKeyEqual(
+            self.repo.get_issues(labels=[bug.name]), lambda i: i.id, [4780155]
+        )
         self.assertListKeyEqual(
             self.repo.get_issues(assignee=user, sort="comments", direction="asc"),
             lambda i: i.id,