class IssueHandler(GitHubHandlerBase): """Handle issue creation and modification.""" title = attr.ib(type=str) body = attr.ib(type=str) milestone = attr.ib(type=int, default=None) labels = attr.ib(type=typing.List[Label], default=attr.Factory(list)) assignees = attr.ib(type=typing.List[User], default=attr.Factory(list)) state = attr.ib(default=State.get_default(), type=State) @classmethod def by_number(cls, organization: str, project: str, number: int) -> Issue: """Retrieve issue based on it's number.""" uri = 'repos/{org!s}/{project!s}/issues/{number:d}'.format( org=organization, project=project, number=number) response, _ = cls._call(uri, method='GET') return Issue.from_response(response) def create(self, organization: str, project: str) -> Issue: """Create an issue.""" uri = 'repos/{org!s}/{project!s}/issues'.format(org=organization, project=project) payload = { key: value for key, value in attr.asdict(self).items() if value is not None } response, _ = self._call(uri, payload=payload, method='POST') return Issue.from_response(response) def edit(self, organization: str, project: str, number: int) -> Issue: """Edit existing issue.""" uri = 'repos/{org!s}/{project!s}/issues/{number:d}'.format( org=organization, project=project, number=number) payload = { key: value for key, value in attr.asdict(self).items() if value is not None } response, _ = self._call(uri, payload=payload, method='PATCH') # TODO: report not-changed values return Issue.from_response(response)
"""Issue milestone schema.""" from voluptuous import Any from voluptuous import Required from voluptuous import Schema from voluptuous import Url from githubcap.enums import State from .user import USER_SCHEMA # pylint: disable=no-value-for-parameter MILESTONE_SCHEMA = Schema({ Required("url"): Url(), Required("html_url"): Url(), Required("labels_url"): Url(), Required("id"): int, Required("number"): int, Required("state"): Schema(Any(*State.all_values())), Required("title"): str, Required("description"): Schema(Any(str, None)), Required("creator"): USER_SCHEMA, Required("open_issues"): int, Required("closed_issues"): int, Required("created_at"): str, Required("updated_at"): Schema(Any(str, None)), Required("closed_at"): Schema(Any(str, None)), Required("due_on"): Schema(Any(str, None)) })
class IssuesHandler(GitHubHandlerBase): """Handling issues querying.""" page = attr.ib(default=1, type=int) per_page = attr.ib(default=GitHubHandlerBase.DEFAULT_PER_PAGE, type=int) filter = attr.ib(default=Filtering.get_default(), type=Filtering) state = attr.ib(default=State.get_default(), type=State) labels = attr.ib(default=attr.Factory(list), type=typing.List[Label]) sort = attr.ib(default=Sorting.get_default(), type=Sorting) direction = attr.ib(default=SortingDirection.get_default(), type=SortingDirection) since = attr.ib(default=None, type=str) milestone = attr.ib(default=attr.Factory(lambda: '*'), type=str) assignee = attr.ib(default=attr.Factory(lambda: '*'), type=str) creator = attr.ib(default=None, type=str) mentioned = attr.ib(default=None, type=str) @milestone.validator def milestone_validator(self, _, value: typing.Any) -> None: # pylint: disable=no-self-use """Validate supplied milestone number value.""" if isinstance(value, int): if value < 0: raise ValueError( "Integer representation of a milestone has to be non-negative integer" ) elif not isinstance(value, str) and value is not None: raise ValueError( "Unknown milestone representation supplied {!r} of type {!s}". format(value, type(value))) def _get_query_string(self) -> str: """Get query string for parametrized queries.""" ret = '' for key, value in attr.asdict(self).items(): if key == 'since': if value is None: continue if isinstance(value, datetime): value = serialize_datetime(value) if key in ('assignee', 'creator', 'mentioned') and value is None: continue if key == 'labels': if not value: continue value = ",".join(value) if ret: ret += '&' ret += '{!s}={!s}'.format( key, str(value) if value is not None else 'none') return ret def list_assigned_issues(self, organization: str = None) -> Issue: """List all assigned issues for the given organization - if organization is None, all issues are listed.""" if organization: base_uri = 'orgs/{!s}/issues'.format(organization) else: base_uri = 'issues' for item in self._do_listing(base_uri): yield Issue.from_response(item) def list_issues(self, organization: str, project: str) -> Issue: """List issues for the given organization/owner and project.""" base_uri = 'repos/{!s}/{!s}/issues'.format(organization, project) for item in self._do_listing(base_uri): yield Issue.from_response(item)
class IssuesHandler(GitHubHandlerBase): page = attr.ib(default=1, type=int) per_page = attr.ib(default=GitHubHandlerBase.DEFAULT_PER_PAGE, type=int) filter = attr.ib(default=Filtering.get_default(), type=Filtering) state = attr.ib(default=State.get_default(), type=State) labels = attr.ib(default=attr.Factory(list), type=list) sort = attr.ib(default=Sorting.get_default(), type=Sorting) direction = attr.ib(default=SortingDirection.get_default(), type=SortingDirection) since = attr.ib(default=None, type=datetime) milestone = attr.ib(default=attr.Factory(lambda: '*'), type=str) assignee = attr.ib(default=attr.Factory(lambda: '*'), type=str) creator = attr.ib(default=None, type=str) mentioned = attr.ib(default=None, type=str) @milestone.validator def milestone_validator(self, _, value): if isinstance(value, int): if value < 0: raise ValueError( "Integer representation of a milestone has to be non-negative integer" ) elif not isinstance(value, str) and value is not None: raise ValueError( "Unknown milestone representation supplied {!r} of type {!s}". format(value, type(value))) def _get_query_string(self): ret = '' for key, value in attr.asdict(self).items(): if key == 'since' and value is None: continue if key in ('assignee', 'creator', 'mentioned') and value is None: continue if key == 'labels': if not value: continue value = ",".join(value) if ret: ret += '&' ret += '{!s}={!s}'.format( key, str(value) if value is not None else 'none') return ret def list_assigned_issues(self, organization=None): if organization: base_uri = 'orgs/{!s}/issues'.format(organization) else: base_uri = 'issues' for item in self._do_listing(base_uri): validate_response(ISSUE_SCHEMA, item) # TODO: yield instances yield item def list_issues(self, organization, project): base_uri = 'repos/{!s}/{!s}/issues'.format(organization, project) for item in self._do_listing(base_uri): validate_response(ISSUE_SCHEMA, item) # TODO: yield instances yield item