Ejemplo n.º 1
0
 def test_github_installation_token(self):
     itoken = GitHubInstallationToken(60731, self.token)
     data = get(itoken, '/installation/repositories')
     self.assertEqual(data['total_count'], 1)
     self.assertEqual(data['repositories'][0]['full_name'],
                      'gitmate-test-org/test')
     self.assertEqual(itoken.jwt, self.token)
Ejemplo n.º 2
0
    def raw_search(token, raw_query):
        """
        Handles a GitHub search.

        Search syntax reference at
        https://help.github.com/articles/understanding-the-search-syntax/

        :param token:        A GitHubToken object to use for authentication.
        :param raw_query:    A string with the search query following syntax.
        :yields:             Search results as GitHubIssue(...) and
                             GitHubMergeRequest(...) objects for Issues and
                             Merge Requests respectively.
        """
        base_url = '/search/issues'
        query_params = {'q': raw_query, 'per_page': '100'}
        resp = get(token, base_url, query_params)

        issue_url_re = re.compile(
            r'https://(?:.+)/(\S+)/(\S+)/(issues|pull)/(\d+)')
        for item in resp:
            user, repo, item_type, item_number = issue_url_re.match(
                item['html_url']).groups()
            if item_type == 'issues':
                yield GitHubIssue.from_data(item, token, user + '/' + repo,
                                            int(item_number))
            elif item_type == 'pull':
                yield GitHubMergeRequest.from_data(item, token,
                                                   user + '/' + repo,
                                                   int(item_number))
Ejemplo n.º 3
0
 def billable_users(self) -> int:
     """
     Number of paying/registered users on the organization.
     """
     try:
         return len(get(self._token, self._url + '/members'))
     except RuntimeError:
         return 1
Ejemplo n.º 4
0
 def get_full_data():
     """
     Updates the incomplete issue data with the PR data to make it
     complete.
     """
     # Ignore PyLintBear (E1101), its type inference is too stupid
     issue_data.update(get(self._token, self._mr_url))
     return issue_data
Ejemplo n.º 5
0
 def reactions(self) -> Set[GitHubReaction]:
     """
     Retrieves the reactions / award emojis applied on the issue.
     """
     url = self._url + '/reactions'
     reactions = get(self._token, url, headers=PREVIEW_HEADER)
     return {GitHubReaction.from_data(r, self._token, self, r['id'])
             for r in reactions}
Ejemplo n.º 6
0
 def master_repositories(self):
     """
     Retrieves repositories the user has admin access to.
     """
     repo_list = get(self._token, '/user/repos')
     return {
         GitHubRepository.from_data(repo, self._token, repo['full_name'])
         for repo in repo_list if repo['permissions']['admin']
     }
Ejemplo n.º 7
0
 def unassign(self, *users: Set[GitHubUser]):
     """
     Removes the user from the assignees of the issue.
     :param users: Username of the user to be unassigned.
     """
     url = self._url + '/assignees'
     delete(self._token, url,
            {'assignees': [user.username for user in users]})
     self.data = get(self._token, self._url)
Ejemplo n.º 8
0
 def repositories(self) -> Set[GitHubRepository]:
     """
     Returns the set of repositories this installation has access to.
     """
     data = get(self._api_token, '/installation/repositories')
     return {
         GitHubRepository.from_data(repo, self._api_token, repo['id'])
         for repo in data['repositories']
     }
Ejemplo n.º 9
0
    def repositories(self) -> Set[Repository]:
        """
        Returns the list of repositories contained in this organization.
        """
        from IGitt.GitHub.GitHubRepository import GitHubRepository

        return {
            GitHubRepository.from_data(repo, self._token, repo['id'])
            for repo in get(self._token, self._url + '/repos')
        }
Ejemplo n.º 10
0
    def filter_issues(self, state: str='opened') -> set:
        """
        Filters the issues from the repository based on properties.

        :param state: 'opened' or 'closed' or 'all'.
        """
        params = {'state': GH_ISSUE_STATE_TRANSLATION[state]}
        return {GitHubIssue.from_data(res, self._token,
                                      self.full_name, res['number'])
                for res in get(self._token, self._url + '/issues', params)
                if 'pull_request' not in res}
Ejemplo n.º 11
0
    def installed_repositories(self, installation_id: int):
        """
        List repositories that are accessible to the authenticated user for an
        installation.
        """
        # Don't move to module code, causes circular dependencies
        from IGitt.GitHub.GitHubRepository import GitHubRepository

        repos = get(self._token, '/user/installations/{}/repositories'.format(
            installation_id), headers=PREVIEW_HEADER)['repositories']
        return {GitHubRepository.from_data(repo, self._token, repo['id'])
                for repo in repos}
Ejemplo n.º 12
0
    def combined_status(self) -> Status:
        """
        Retrieves a combined status of all the commits.

        :return:
            Status.FAILED if any of the commits report as error or failure or
            canceled
            Status.PENDING if there are no statuses or a commit is pending or a
            test is running
            Status.SUCCESS if the latest status for all commits is success
        """
        url = self._url + '/status'
        return INV_GH_STATE_TRANSLATION[get(self._token, url)['state']]
Ejemplo n.º 13
0
 def _get_data(self):
     # Note: A GitHub reaction cannot be retrieved using a GET request, it
     # has to retrieved as a list and filtered for the match.
     if not getattr(self, '_list', None):
         setattr(self, '_list', get(self._token, self._url,
                                    headers=PREVIEW_HEADER))
     try:
         return list(filter(lambda x: x['id'] == self._identifier,
                            getattr(self, '_list')))[0]
     except IndexError:
         raise RuntimeError({
             'message': 'Not Found',
             'documentation_url': 'https://developer.github.com/v3'}, 404)
Ejemplo n.º 14
0
    def merge_requests(self) -> set:
        """
        Retrieves a set of merge request objects.

        >>> from os import environ
        >>> repo = GitHubRepository(environ['GITHUB_TEST_TOKEN'],
        ...                         'gitmate-test-user/test')
        >>> len(repo.merge_requests)
        3
        """
        from IGitt.GitHub.GitHubMergeRequest import GitHubMergeRequest
        return {GitHubMergeRequest(self._token, self.full_name, res['number'])
                for res in get(self._token, self._url + '/pulls')}
Ejemplo n.º 15
0
 def owners(self) -> Set[GitHubUser]:
     """
     Returns the user handles of all admin users.
     """
     try:
         return {
             GitHubUser.from_data(user, self._token, user['login'])
             for user in get(self._token,
                             self._url + '/members',
                             params={'role': 'admin'})
         }
     except RuntimeError:
         return {GitHubUser(self._token, self.name)}
Ejemplo n.º 16
0
    def available_labels(self):
        """
        Retrieves a set of captions that are available for labelling bugs.

        >>> from os import environ
        >>> issue = GitHubIssue(GitHubToken(environ['GITHUB_TEST_TOKEN']),
        ...                     'gitmate-test-user/test', 1)
        >>> sorted(issue.available_labels)
        ['a', 'b', 'c']

        :return: A set of label captions (str).
        """
        return {label['name'] for label in get(
            self._token, '/repos/' + self._repository + '/labels')}
Ejemplo n.º 17
0
    def delete_hook(self, url: str):
        """
        Deletes all webhooks to the given URL.

        :param url: The URL to not fire the webhook to anymore.
        :raises RuntimeError: If something goes wrong (network, auth...).
        """
        hook_url = self._url + '/hooks'
        hooks = get(self._token, hook_url)

        # Do not use self.hooks since id of the hook is needed
        for hook in hooks:
            if hook['config'].get('url', None) == url:
                delete(self._token, hook_url + '/' + str(hook['id']))
Ejemplo n.º 18
0
    def _get_data(self):
        issue_data = get(self._token, self._url)

        def get_full_data():
            """
            Updates the incomplete issue data with the PR data to make it
            complete.
            """
            # Ignore PyLintBear (E1101), its type inference is too stupid
            issue_data.update(get(self._token, self._mr_url))
            return issue_data

        # If issue data is sufficient, don't even get MR data
        return PossiblyIncompleteDict(issue_data, get_full_data)
Ejemplo n.º 19
0
    def get_labels(self):
        """
        Retrieves the labels of the repository.

        >>> from os import environ
        >>> repo = GitHubRepository(GitHubToken(environ['GITHUB_TEST_TOKEN']),
        ...                         'gitmate-test-user/test')
        >>> sorted(repo.get_labels())
        ['a', 'b', 'c']

        :return: A set of strings containing the label captions.
        """
        return {label['name']
                for label in get(self._token, self._url + '/labels')}
Ejemplo n.º 20
0
    def hooks(self):
        """
        Retrieves all URLs this repository is hooked to.

        :return: Set of URLs (str).
        """
        hook_url = self._url + '/hooks'
        hooks = get(self._token, hook_url)

        # Use get since some hooks might not have a config - stupid github
        results = {hook['config'].get('url') for hook in hooks}
        results.discard(None)

        return results
Ejemplo n.º 21
0
    def affected_files(self):
        """
        Retrieves affected files from a GitHub pull request.

        >>> from os import environ
        >>> pr = GitHubMergeRequest(GitHubToken(environ['GITHUB_TEST_TOKEN']),
        ...                         'gitmate-test-user/test', 7)
        >>> pr.affected_files
        {'README.md'}

        :return: A set of filenames.
        """
        files = get(self._token, self._mr_url + '/files')
        return {file['filename'] for file in files}
Ejemplo n.º 22
0
    def owned_repositories(self):
        """
        Retrieves repositories owned by the authenticated user.

        >>> from os import environ
        >>> github = GitHub(GitHubToken(environ['GITHUB_TEST_TOKEN']))
        >>> sorted(map(lambda x: x.full_name, github.owned_repositories))
        ['gitmate-test-user/test']

        :return: A set of full repository names.
        """
        repo_list = get(self._token, '/user/repos', {'affiliation': 'owner'})
        return {
            GitHubRepository.from_data(repo, self._token, repo['full_name'])
            for repo in repo_list
        }
Ejemplo n.º 23
0
    def write_repositories(self):
        """
        Retrieves the full names of repositories this user can write to.

        >>> from os import environ
        >>> github = GitHub(GitHubToken(environ['GITHUB_TEST_TOKEN']))
        >>> sorted(map(lambda x: x.full_name, github.write_repositories))
        ['gitmate-test-user/test', 'sils/gitmate-test']

        :return: A set of strings.
        """
        repo_list = get(self._token, '/user/repos')
        return {
            GitHubRepository.from_data(repo, self._token, repo['full_name'])
            for repo in repo_list if repo['permissions']['push']
        }
Ejemplo n.º 24
0
    def commits(self):
        """
        Retrieves a tuple of commit objects that are included in the PR.

        >>> from os import environ
        >>> pr = GitHubMergeRequest(GitHubToken(environ['GITHUB_TEST_TOKEN']),
        ...                         'gitmate-test-user/test', 7)
        >>> [commit.sha for commit in pr.commits]
        ['f6d2b7c66372236a090a2a74df2e47f42a54456b']

        :return: A tuple of commit objects.
        """
        commits = get(self._token, self._mr_url + '/commits')
        return tuple(
            GitHubCommit.from_data(commit, self._token, self._repository,
                                   commit['sha']) for commit in commits)
Ejemplo n.º 25
0
    def get_installations(self, jwt):
        """
        Gets the installations this user has access to.

        :param jwt: The GitHubJsonWebToken required to fetch data.
        """
        # Don't move to module code, causes circular dependencies
        from IGitt.GitHub.GitHubInstallation import GitHubInstallation

        resp = get(
            self._token, '/user/installations', headers=PREVIEW_HEADER)
        return {
            GitHubInstallation.from_data(
                i, GitHubInstallationToken(i['id'], jwt), i['id'])
            for i in resp['installations']
        }
Ejemplo n.º 26
0
 def unified_diff(self):
     """
     Retrieves the unified diff for the commit excluding the diff index.
     """
     difflines = str(
         get(self._token,
             self._url,
             headers={'Accept': 'application/vnd.github.v3.diff'
                      })).strip().splitlines()
     # getting rid of the indexing stuff from git diff e.g. removing lines
     # ``diff --git a/somefile b/somefile
     # index 1da2df..2dacdf 100644``
     return '\n'.join([
         diff for diff in difflines if not diff.startswith('diff --git')
         and not diff.startswith('index')
     ])
Ejemplo n.º 27
0
    def get_permission_level(self, user) -> AccessLevel:
        """
        Retrieves the permission level for the specified user on this
        repository.

        Note that this request can be made only if the access token used here
        has atleast write access to the repository. If not, a HTTP 403 occurs.
        """
        url = self._url + '/collaborators/{}/permission'.format(user.username)
        data = get(self._token, url)
        return {
            'admin': AccessLevel.ADMIN,
            'write': AccessLevel.CAN_WRITE,
            'read': AccessLevel.CAN_READ,
            'none': AccessLevel.NONE,
        }.get(data['permission'])
Ejemplo n.º 28
0
    def comments(self):
        r"""
        Retrieves comments from the issue.

        >>> from os import environ
        >>> issue = GitHubIssue(GitHubToken(environ['GITHUB_TEST_TOKEN']),
        ...                     'gitmate-test-user/test', 9)
        >>> comments = issue.comments

        Now we can e.g. access the last comment:

        >>> comments[-1].body
        'Do not comment here.\n'

        :return: A list of Comment objects.
        """
        return [GitHubComment.from_data(result, self._token, self._repository,
                                        CommentType.ISSUE, result['id'])
                for result in get(self._token, self._url + '/comments')]
Ejemplo n.º 29
0
    def commits(self):
        """
        Retrieves the set of commits in this repository.

        :return: A set of GitHubCommit objects.
        """
        # Don't move to module, leads to circular imports
        from IGitt.GitHub.GitHubCommit import GitHubCommit

        try:
            return {GitHubCommit.from_data(commit,
                                           self._token,
                                           self.full_name,
                                           commit['sha'])
                    for commit in get(self._token, self._url + '/commits')}
        except RuntimeError as ex:
            # Repository is empty. GitHub returns 409.
            if ex.args[1] == 409:
                return set()
            raise ex  # dont cover, this is the real exception
Ejemplo n.º 30
0
    def get_statuses(self) -> Set[CommitStatus]:
        """
        Retrieves the all commit statuses.

        :return: A (frozen)set of CommitStatus objects.
        :raises RuntimeError: If something goes wrong (network, auth...).
        """
        url = self._url + '/statuses'
        statuses = get(self._token, url)

        # Only the first of each context is the one we want
        result = set()
        contexts = set()
        for status in statuses:
            if status['context'] not in contexts:
                result.add(
                    CommitStatus(INV_GH_STATE_TRANSLATION[status['state']],
                                 status['description'], status['context'],
                                 status['target_url']))
                contexts.add(status['context'])

        return result