From e306a3209b1ef49e4719256de0eff8cef460f277 Mon Sep 17 00:00:00 2001 From: Trim21 Date: Fri, 7 Jul 2023 17:43:29 +0800 Subject: [PATCH] Merge `Issue.pyi` back to source (#2568) Co-authored-by: Enrico Minack --- github/GithubObject.py | 19 +- github/Issue.py | 397 ++++++++++++++++------------------------- github/Issue.pyi | 100 ----------- 3 files changed, 161 insertions(+), 355 deletions(-) delete mode 100644 github/Issue.pyi diff --git a/github/GithubObject.py b/github/GithubObject.py index 6e59d48f..304ceb33 100644 --- a/github/GithubObject.py +++ b/github/GithubObject.py @@ -46,15 +46,15 @@ from typing import ( Any, Callable, Dict, - Generic, List, Optional, + Tuple, Type, Union, ) from dateutil import parser -from typing_extensions import TypeGuard +from typing_extensions import Protocol, TypeGuard from . import Consts from .GithubException import BadAttributeException, IncompletableObject @@ -63,15 +63,16 @@ if TYPE_CHECKING: from .Requester import Requester T = typing.TypeVar("T") +T_co = typing.TypeVar("T_co", covariant=True) -class Attribute(Generic[T]): +class Attribute(Protocol[T_co]): @property - def value(self) -> T: + def value(self) -> T_co: raise NotImplementedError -class _NotSetType(Attribute): +class _NotSetType: def __repr__(self): return "NotSet" @@ -97,15 +98,15 @@ def is_defined(v: Union[T, _NotSetType]) -> TypeGuard[T]: return not isinstance(v, _NotSetType) -def is_undefined(v: Any) -> TypeGuard[_NotSetType]: +def is_undefined(v: Union[T, _NotSetType]) -> TypeGuard[_NotSetType]: return isinstance(v, _NotSetType) -def is_optional(v, type: Type[T]) -> TypeGuard[Opt[T]]: +def is_optional(v, type: Union[Type, Tuple[Type, ...]]) -> bool: return isinstance(v, _NotSetType) or isinstance(v, type) -def is_optional_list(v, type: Type[T]) -> TypeGuard[Opt[List[T]]]: +def is_optional_list(v, type: Union[Type, Tuple[Type, ...]]) -> bool: return ( isinstance(v, _NotSetType) or isinstance(v, list) @@ -113,7 +114,7 @@ def is_optional_list(v, type: Type[T]) -> TypeGuard[Opt[List[T]]]: ) -class _ValuedAttribute(Attribute, Generic[T]): +class _ValuedAttribute(Attribute[T]): def __init__(self, value: T): self._value = value diff --git a/github/Issue.py b/github/Issue.py index b5bacdbc..c2153f3d 100644 --- a/github/Issue.py +++ b/github/Issue.py @@ -41,9 +41,11 @@ # along with PyGithub. If not, see . # # # ################################################################################ +from __future__ import annotations import urllib.parse from datetime import datetime +from typing import TYPE_CHECKING import github.GithubObject import github.IssueComment @@ -52,159 +54,157 @@ import github.IssuePullRequest import github.Label import github.Milestone import github.NamedUser -import github.PaginatedList +import github.PullRequest import github.Reaction import github.Repository import github.TimelineEvent +from github import Consts +from github.GithubObject import ( + Attribute, + CompletableGithubObject, + NotSet, + Opt, + is_defined, + is_optional, + is_optional_list, + is_undefined, +) +from github.PaginatedList import PaginatedList -from . import Consts +if TYPE_CHECKING: + from github.IssueComment import IssueComment + from github.IssueEvent import IssueEvent + from github.IssuePullRequest import IssuePullRequest + from github.Label import Label + from github.Milestone import Milestone + from github.NamedUser import NamedUser + from github.PullRequest import PullRequest + from github.Reaction import Reaction + from github.Repository import Repository + from github.TimelineEvent import TimelineEvent -class Issue(github.GithubObject.CompletableGithubObject): +class Issue(CompletableGithubObject): """ This class represents Issues. The reference can be found here https://docs.github.com/en/rest/reference/issues """ + def _initAttributes(self) -> None: + self._id: Attribute[int] = NotSet + self._active_lock_reason: Attribute[str | None] = NotSet + self._assignee: Attribute[NamedUser | None] = NotSet + self._assignees: Attribute[list[NamedUser]] = NotSet + self._body: Attribute[str] = NotSet + self._closed_at: Attribute[datetime] = NotSet + self._closed_by: Attribute[NamedUser] = NotSet + self._comments: Attribute[int] = NotSet + self._comments_url: Attribute[str] = NotSet + self._created_at: Attribute[datetime] = NotSet + self._events_url: Attribute[str] = NotSet + self._html_url: Attribute[str] = NotSet + self._labels: Attribute[list[Label]] = NotSet + self._labels_url: Attribute[str] = NotSet + self._locked: Attribute[bool] = NotSet + self._milestone: Attribute[Milestone] = NotSet + self._number: Attribute[int] = NotSet + self._pull_request: Attribute[IssuePullRequest] = NotSet + self._repository: Attribute[Repository] = NotSet + self._state: Attribute[str] = NotSet + self._state_reason: Attribute[str | None] = NotSet + self._title: Attribute[str] = NotSet + self._updated_at: Attribute[datetime] = NotSet + self._url: Attribute[str] = NotSet + self._user: Attribute[NamedUser] = NotSet + def __repr__(self): return self.get__repr__( {"number": self._number.value, "title": self._title.value} ) @property - def assignee(self): - """ - :type: :class:`github.NamedUser.NamedUser` - """ + def assignee(self) -> NamedUser | None: self._completeIfNotSet(self._assignee) return self._assignee.value @property - def assignees(self): - """ - :type: list of :class:`github.NamedUser.NamedUser` - """ + def assignees(self) -> list[NamedUser]: self._completeIfNotSet(self._assignees) return self._assignees.value @property - def body(self): - """ - :type: string - """ + def body(self) -> str: self._completeIfNotSet(self._body) return self._body.value @property - def closed_at(self): - """ - :type: datetime - """ + def closed_at(self) -> datetime: self._completeIfNotSet(self._closed_at) return self._closed_at.value @property - def closed_by(self): - """ - :type: :class:`github.NamedUser.NamedUser` - """ + def closed_by(self) -> NamedUser | None: self._completeIfNotSet(self._closed_by) return self._closed_by.value @property - def comments(self): - """ - :type: integer - """ + def comments(self) -> int: self._completeIfNotSet(self._comments) return self._comments.value @property - def comments_url(self): - """ - :type: string - """ + def comments_url(self) -> str: self._completeIfNotSet(self._comments_url) return self._comments_url.value @property - def created_at(self): - """ - :type: datetime - """ + def created_at(self) -> datetime: self._completeIfNotSet(self._created_at) return self._created_at.value @property - def events_url(self): - """ - :type: string - """ + def events_url(self) -> str: self._completeIfNotSet(self._events_url) return self._events_url.value @property - def html_url(self): - """ - :type: string - """ + def html_url(self) -> str: self._completeIfNotSet(self._html_url) return self._html_url.value @property - def id(self): - """ - :type: integer - """ + def id(self) -> int: self._completeIfNotSet(self._id) return self._id.value @property - def labels(self): - """ - :type: list of :class:`github.Label.Label` - """ + def labels(self) -> list[Label]: self._completeIfNotSet(self._labels) return self._labels.value @property - def labels_url(self): - """ - :type: string - """ + def labels_url(self) -> str: self._completeIfNotSet(self._labels_url) return self._labels_url.value @property - def milestone(self): - """ - :type: :class:`github.Milestone.Milestone` - """ + def milestone(self) -> Milestone: self._completeIfNotSet(self._milestone) return self._milestone.value @property - def number(self): - """ - :type: integer - """ + def number(self) -> int: self._completeIfNotSet(self._number) return self._number.value @property - def pull_request(self): - """ - :type: :class:`github.IssuePullRequest.IssuePullRequest` - """ + def pull_request(self) -> IssuePullRequest | None: self._completeIfNotSet(self._pull_request) return self._pull_request.value @property - def repository(self): - """ - :type: :class:`github.Repository.Repository` - """ + def repository(self) -> Repository: self._completeIfNotSet(self._repository) - if self._repository is github.GithubObject.NotSet: + if is_undefined(self._repository): # The repository was not set automatically, so it must be looked up by url. repo_url = "/".join(self.url.split("/")[:-2]) self._repository = github.GithubObject._ValuedAttribute( @@ -215,73 +215,48 @@ class Issue(github.GithubObject.CompletableGithubObject): return self._repository.value @property - def state(self): - """ - :type: string - """ + def state(self) -> str: self._completeIfNotSet(self._state) return self._state.value @property - def state_reason(self): - """ - :type: string - """ + def state_reason(self) -> str | None: self._completeIfNotSet(self._state_reason) return self._state_reason.value @property - def title(self): - """ - :type: string - """ + def title(self) -> str: self._completeIfNotSet(self._title) return self._title.value @property - def updated_at(self): - """ - :type: datetime - """ + def updated_at(self) -> datetime: self._completeIfNotSet(self._updated_at) return self._updated_at.value @property - def url(self): - """ - :type: string - """ + def url(self) -> str: self._completeIfNotSet(self._url) return self._url.value @property - def user(self): - """ - :type: :class:`github.NamedUser.NamedUser` - """ + def user(self) -> NamedUser: self._completeIfNotSet(self._user) return self._user.value @property - def locked(self): - """ - :type: bool - """ + def locked(self) -> bool: self._completeIfNotSet(self._locked) return self._locked.value @property - def active_lock_reason(self): - """ - :type: string - """ + def active_lock_reason(self) -> str | None: self._completeIfNotSet(self._active_lock_reason) return self._active_lock_reason.value - def as_pull_request(self): + def as_pull_request(self) -> PullRequest: """ :calls: `GET /repos/{owner}/{repo}/pulls/{number} `_ - :rtype: :class:`github.PullRequest.PullRequest` """ headers, data = self._requester.requestJsonAndCheck( "GET", "/pulls/".join(self.url.rsplit("/issues/", 1)) @@ -290,11 +265,9 @@ class Issue(github.GithubObject.CompletableGithubObject): self._requester, headers, data, completed=True ) - def add_to_assignees(self, *assignees): + def add_to_assignees(self, *assignees: NamedUser | str) -> None: """ :calls: `POST /repos/{owner}/{repo}/issues/{number}/assignees `_ - :param assignee: :class:`github.NamedUser.NamedUser` or string - :rtype: None """ assert all( isinstance(element, (github.NamedUser.NamedUser, str)) @@ -313,11 +286,9 @@ class Issue(github.GithubObject.CompletableGithubObject): ) self._useAttributes(data) - def add_to_labels(self, *labels): + def add_to_labels(self, *labels: Label | str) -> None: """ :calls: `POST /repos/{owner}/{repo}/issues/{number}/labels `_ - :param label: :class:`github.Label.Label` or string - :rtype: None """ assert all( isinstance(element, (github.Label.Label, str)) for element in labels @@ -330,11 +301,9 @@ class Issue(github.GithubObject.CompletableGithubObject): "POST", f"{self.url}/labels", input=post_parameters ) - def create_comment(self, body): + def create_comment(self, body: str) -> IssueComment: """ :calls: `POST /repos/{owner}/{repo}/issues/{number}/comments `_ - :param body: string - :rtype: :class:`github.IssueComment.IssueComment` """ assert isinstance(body, str), body post_parameters = { @@ -347,10 +316,9 @@ class Issue(github.GithubObject.CompletableGithubObject): self._requester, headers, data, completed=True ) - def delete_labels(self): + def delete_labels(self) -> None: """ :calls: `DELETE /repos/{owner}/{repo}/issues/{number}/labels `_ - :rtype: None """ headers, data = self._requester.requestJsonAndCheck( "DELETE", f"{self.url}/labels" @@ -358,87 +326,67 @@ class Issue(github.GithubObject.CompletableGithubObject): def edit( self, - title=github.GithubObject.NotSet, - body=github.GithubObject.NotSet, - assignee=github.GithubObject.NotSet, - state=github.GithubObject.NotSet, - milestone=github.GithubObject.NotSet, - labels=github.GithubObject.NotSet, - assignees=github.GithubObject.NotSet, - state_reason=github.GithubObject.NotSet, - ): + title: Opt[str] = NotSet, + body: Opt[str] = NotSet, + assignee: Opt[str | NamedUser | None] = NotSet, + state: Opt[str] = NotSet, + milestone: Opt[Milestone | None] = NotSet, + labels: Opt[list[str]] = NotSet, + assignees: Opt[list[NamedUser | str]] = NotSet, + state_reason: Opt[str] = NotSet, + ) -> None: """ :calls: `PATCH /repos/{owner}/{repo}/issues/{number} `_ - :param title: string - :param body: string - :param assignee: string or :class:`github.NamedUser.NamedUser` or None - :param state: string - :param milestone: :class:`github.Milestone.Milestone` or None - :param labels: list of string - :param assignees: list of string or :class:`github.NamedUser.NamedUser` - :param state_reason: string - :rtype: None + :param assignee: deprecated, use `assignees` instead. `assignee=None` means to remove current assignee. + :param milestone: `milestone=None` means to remove current milestone. """ - assert title is github.GithubObject.NotSet or isinstance(title, str), title - assert body is github.GithubObject.NotSet or isinstance(body, str), body - assert ( - assignee is github.GithubObject.NotSet - or assignee is None - or isinstance(assignee, github.NamedUser.NamedUser) - or isinstance(assignee, str) + assert is_optional(title, str), title + assert is_optional(body, str), body + assert assignee is None or is_optional( + assignee, (github.NamedUser.NamedUser, str) ), assignee - assert assignees is github.GithubObject.NotSet or all( - isinstance(element, github.NamedUser.NamedUser) or isinstance(element, str) - for element in assignees - ), assignees - assert state is github.GithubObject.NotSet or isinstance(state, str), state - assert ( - milestone is github.GithubObject.NotSet - or milestone is None - or isinstance(milestone, github.Milestone.Milestone) + assert is_optional_list(assignees, (github.NamedUser.NamedUser, str)), assignees + assert is_optional(state, str), state + assert milestone is None or is_optional( + milestone, github.Milestone.Milestone ), milestone - assert labels is github.GithubObject.NotSet or all( - isinstance(element, str) for element in labels - ), labels - post_parameters = dict() - if title is not github.GithubObject.NotSet: - post_parameters["title"] = title - if body is not github.GithubObject.NotSet: - post_parameters["body"] = body - if assignee is not github.GithubObject.NotSet: - if isinstance(assignee, str): - post_parameters["assignee"] = assignee - else: - post_parameters["assignee"] = assignee._identity if assignee else "" - if assignees is not github.GithubObject.NotSet: + assert is_optional_list(labels, str), labels + + post_parameters = NotSet.remove_unset_items( + { + "title": title, + "body": body, + "state": state, + "state_reason": state_reason, + "labels": labels, + "assignee": assignee._identity + if isinstance(assignee, github.NamedUser.NamedUser) + else (assignee or ""), + "milestone": milestone._identity + if isinstance(milestone, github.Milestone.Milestone) + else (milestone or ""), + } + ) + + if is_defined(assignees): post_parameters["assignees"] = [ element._identity if isinstance(element, github.NamedUser.NamedUser) else element for element in assignees ] - if state is not github.GithubObject.NotSet: - post_parameters["state"] = state - if state_reason is not github.GithubObject.NotSet: - post_parameters["state_reason"] = state_reason - if milestone is not github.GithubObject.NotSet: - post_parameters["milestone"] = milestone._identity if milestone else "" - if labels is not github.GithubObject.NotSet: - post_parameters["labels"] = labels + headers, data = self._requester.requestJsonAndCheck( "PATCH", self.url, input=post_parameters ) self._useAttributes(data) - def lock(self, lock_reason): + def lock(self, lock_reason: str) -> None: """ :calls: `PUT /repos/{owner}/{repo}/issues/{issue_number}/lock `_ - :param lock_reason: string - :rtype: None """ assert isinstance(lock_reason, str), lock_reason - put_parameters = dict() - put_parameters["lock_reason"] = lock_reason + put_parameters = {"lock_reason": lock_reason} headers, data = self._requester.requestJsonAndCheck( "PUT", f"{self.url}/lock", @@ -446,20 +394,17 @@ class Issue(github.GithubObject.CompletableGithubObject): headers={"Accept": Consts.mediaTypeLockReasonPreview}, ) - def unlock(self): + def unlock(self) -> None: """ :calls: `DELETE /repos/{owner}/{repo}/issues/{issue_number}/lock `_ - :rtype: None """ headers, data = self._requester.requestJsonAndCheck( "DELETE", f"{self.url}/lock" ) - def get_comment(self, id): + def get_comment(self, id: int) -> IssueComment: """ :calls: `GET /repos/{owner}/{repo}/issues/comments/{id} `_ - :param id: integer - :rtype: :class:`github.IssueComment.IssueComment` """ assert isinstance(id, int), id headers, data = self._requester.requestJsonAndCheck( @@ -469,29 +414,29 @@ class Issue(github.GithubObject.CompletableGithubObject): self._requester, headers, data, completed=True ) - def get_comments(self, since=github.GithubObject.NotSet): + def get_comments( + self, since: Opt[datetime] = NotSet + ) -> PaginatedList[IssueComment]: """ :calls: `GET /repos/{owner}/{repo}/issues/{number}/comments `_ - :param since: datetime format YYYY-MM-DDTHH:MM:SSZ - :rtype: :class:`github.PaginatedList.PaginatedList` of :class:`github.IssueComment.IssueComment` """ - assert since is github.GithubObject.NotSet or isinstance(since, datetime), since - url_parameters = dict() - if since is not github.GithubObject.NotSet: + url_parameters = {} + if is_defined(since): + assert isinstance(since, datetime), since url_parameters["since"] = since.strftime("%Y-%m-%dT%H:%M:%SZ") - return github.PaginatedList.PaginatedList( + + return PaginatedList( github.IssueComment.IssueComment, self._requester, f"{self.url}/comments", url_parameters, ) - def get_events(self): + def get_events(self) -> PaginatedList[IssueEvent]: """ :calls: `GET /repos/{owner}/{repo}/issues/{issue_number}/events `_ - :rtype: :class:`github.PaginatedList.PaginatedList` of :class:`github.IssueEvent.IssueEvent` """ - return github.PaginatedList.PaginatedList( + return PaginatedList( github.IssueEvent.IssueEvent, self._requester, f"{self.url}/events", @@ -499,20 +444,17 @@ class Issue(github.GithubObject.CompletableGithubObject): headers={"Accept": Consts.mediaTypeLockReasonPreview}, ) - def get_labels(self): + def get_labels(self) -> PaginatedList[Label]: """ :calls: `GET /repos/{owner}/{repo}/issues/{number}/labels `_ - :rtype: :class:`github.PaginatedList.PaginatedList` of :class:`github.Label.Label` """ - return github.PaginatedList.PaginatedList( + return PaginatedList( github.Label.Label, self._requester, f"{self.url}/labels", None ) - def remove_from_assignees(self, *assignees): + def remove_from_assignees(self, *assignees: NamedUser | str) -> None: """ :calls: `DELETE /repos/{owner}/{repo}/issues/{number}/assignees `_ - :param assignee: :class:`github.NamedUser.NamedUser` or string - :rtype: None """ assert all( isinstance(element, (github.NamedUser.NamedUser, str)) @@ -531,11 +473,9 @@ class Issue(github.GithubObject.CompletableGithubObject): ) self._useAttributes(data) - def remove_from_labels(self, label): + def remove_from_labels(self, label: Label | str) -> None: """ :calls: `DELETE /repos/{owner}/{repo}/issues/{number}/labels/{name} `_ - :param label: :class:`github.Label.Label` or string - :rtype: None """ assert isinstance(label, (github.Label.Label, str)), label if isinstance(label, github.Label.Label): @@ -546,11 +486,9 @@ class Issue(github.GithubObject.CompletableGithubObject): "DELETE", f"{self.url}/labels/{label}" ) - def set_labels(self, *labels): + def set_labels(self, *labels: Label | str) -> None: """ :calls: `PUT /repos/{owner}/{repo}/issues/{number}/labels `_ - :param labels: list of :class:`github.Label.Label` or strings - :rtype: None """ assert all( isinstance(element, (github.Label.Label, str)) for element in labels @@ -563,12 +501,11 @@ class Issue(github.GithubObject.CompletableGithubObject): "PUT", f"{self.url}/labels", input=post_parameters ) - def get_reactions(self): + def get_reactions(self) -> PaginatedList[Reaction]: """ :calls: `GET /repos/{owner}/{repo}/issues/{number}/reactions `_ - :return: :class: :class:`github.PaginatedList.PaginatedList` of :class:`github.Reaction.Reaction` """ - return github.PaginatedList.PaginatedList( + return PaginatedList( github.Reaction.Reaction, self._requester, f"{self.url}/reactions", @@ -576,11 +513,9 @@ class Issue(github.GithubObject.CompletableGithubObject): headers={"Accept": Consts.mediaTypeReactionsPreview}, ) - def create_reaction(self, reaction_type): + def create_reaction(self, reaction_type: str) -> Reaction: """ :calls: `POST /repos/{owner}/{repo}/issues/{number}/reactions `_ - :param reaction_type: string - :rtype: :class:`github.Reaction.Reaction` """ assert isinstance(reaction_type, str), reaction_type post_parameters = { @@ -594,11 +529,9 @@ class Issue(github.GithubObject.CompletableGithubObject): ) return github.Reaction.Reaction(self._requester, headers, data, completed=True) - def delete_reaction(self, reaction_id): + def delete_reaction(self, reaction_id: int) -> bool: """ :calls: `DELETE /repos/{owner}/{repo}/issues/{issue_number}/reactions/{reaction_id} `_ - :param reaction_id: integer - :rtype: bool """ assert isinstance(reaction_id, int), reaction_id status, _, _ = self._requester.requestJson( @@ -608,12 +541,11 @@ class Issue(github.GithubObject.CompletableGithubObject): ) return status == 204 - def get_timeline(self): + def get_timeline(self) -> PaginatedList[TimelineEvent]: """ :calls: `GET /repos/{owner}/{repo}/issues/{number}/timeline `_ - :return: :class: :class:`github.PaginatedList.PaginatedList` of :class:`github.TimelineEvent.TimelineEvent` """ - return github.PaginatedList.PaginatedList( + return PaginatedList( github.TimelineEvent.TimelineEvent, self._requester, f"{self.url}/timeline", @@ -622,37 +554,10 @@ class Issue(github.GithubObject.CompletableGithubObject): ) @property - def _identity(self): + def _identity(self) -> int: return self.number - def _initAttributes(self): - self._active_lock_reason = github.GithubObject.NotSet - self._assignee = github.GithubObject.NotSet - self._assignees = github.GithubObject.NotSet - self._body = github.GithubObject.NotSet - self._closed_at = github.GithubObject.NotSet - self._closed_by = github.GithubObject.NotSet - self._comments = github.GithubObject.NotSet - self._comments_url = github.GithubObject.NotSet - self._created_at = github.GithubObject.NotSet - self._events_url = github.GithubObject.NotSet - self._html_url = github.GithubObject.NotSet - self._id = github.GithubObject.NotSet - self._labels = github.GithubObject.NotSet - self._labels_url = github.GithubObject.NotSet - self._locked = github.GithubObject.NotSet - self._milestone = github.GithubObject.NotSet - self._number = github.GithubObject.NotSet - self._pull_request = github.GithubObject.NotSet - self._repository = github.GithubObject.NotSet - self._state = github.GithubObject.NotSet - self._state_reason = github.GithubObject.NotSet - self._title = github.GithubObject.NotSet - self._updated_at = github.GithubObject.NotSet - self._url = github.GithubObject.NotSet - self._user = github.GithubObject.NotSet - - def _useAttributes(self, attributes): + def _useAttributes(self, attributes) -> None: if "active_lock_reason" in attributes: # pragma no branch self._active_lock_reason = self._makeStringAttribute( attributes["active_lock_reason"] diff --git a/github/Issue.pyi b/github/Issue.pyi deleted file mode 100644 index 64327cef..00000000 --- a/github/Issue.pyi +++ /dev/null @@ -1,100 +0,0 @@ -from datetime import datetime -from typing import Any, Dict, List, Optional, Union - -from github.GithubObject import CompletableGithubObject, _NotSetType -from github.IssueComment import IssueComment -from github.IssueEvent import IssueEvent -from github.IssuePullRequest import IssuePullRequest -from github.Label import Label -from github.Milestone import Milestone -from github.NamedUser import NamedUser -from github.PaginatedList import PaginatedList -from github.PullRequest import PullRequest -from github.Reaction import Reaction -from github.Repository import Repository -from github.TimelineEvent import TimelineEvent - -class Issue(CompletableGithubObject): - def __repr__(self) -> str: ... - @property - def _identity(self) -> int: ... - def _initAttributes(self) -> None: ... - def _useAttributes(self, attributes: Dict[str, Any]) -> None: ... - def add_to_assignees(self, *assignees: Union[NamedUser, str]) -> None: ... - def add_to_labels(self, *labels: Union[Label, str]) -> None: ... - def as_pull_request(self) -> PullRequest: ... - @property - def active_lock_reason(self) -> str: ... - @property - def assignee(self) -> Optional[NamedUser]: ... - @property - def assignees(self) -> List[NamedUser]: ... - @property - def body(self) -> str: ... - @property - def closed_at(self) -> datetime: ... - @property - def closed_by(self) -> Optional[NamedUser]: ... - @property - def comments(self) -> int: ... - @property - def comments_url(self) -> str: ... - def create_comment(self, body: str) -> IssueComment: ... - def create_reaction(self, reaction_type: str) -> Reaction: ... - def get_timeline(self) -> PaginatedList[TimelineEvent]: ... - @property - def created_at(self) -> datetime: ... - def delete_labels(self) -> None: ... - def delete_reaction(self, reaction_id: int) -> bool: ... - def edit( - self, - title: Union[str, _NotSetType] = ..., - body: Union[str, _NotSetType] = ..., - assignee: Optional[Union[str, _NotSetType, NamedUser]] = ..., - state: Union[str, _NotSetType] = ..., - milestone: Optional[Union[Milestone, _NotSetType]] = ..., - labels: Union[_NotSetType, List[str]] = ..., - assignees: Union[_NotSetType, List[str]] = ..., - ) -> None: ... - @property - def events_url(self) -> str: ... - def get_comment(self, id: int) -> IssueComment: ... - def get_comments( - self, since: Union[_NotSetType, datetime] = ... - ) -> PaginatedList[IssueComment]: ... - def get_events(self) -> PaginatedList[IssueEvent]: ... - def get_labels(self) -> PaginatedList[Label]: ... - def get_reactions(self) -> PaginatedList[Reaction]: ... - @property - def html_url(self) -> str: ... - @property - def id(self) -> int: ... - @property - def labels(self) -> List[Label]: ... - @property - def labels_url(self) -> str: ... - def lock(self, lock_reason: str) -> None: ... - @property - def locked(self) -> bool: ... - @property - def milestone(self) -> Optional[Milestone]: ... - @property - def number(self) -> int: ... - @property - def pull_request(self) -> IssuePullRequest: ... - def remove_from_assignees(self, *assignees: Union[NamedUser, str]) -> None: ... - def remove_from_labels(self, label: Union[str, Label]) -> None: ... - @property - def repository(self) -> Repository: ... - def set_labels(self, *labels: Union[str, Label]) -> None: ... - @property - def state(self) -> str: ... - @property - def title(self) -> str: ... - def unlock(self) -> None: ... - @property - def updated_at(self) -> datetime: ... - @property - def url(self) -> str: ... - @property - def user(self) -> NamedUser: ...