10000 Added Collaborator, Contributor and Repository.collaborators(affiliation) by AndreasBackx · Pull Request #731 · sigmavirus24/github3.py · GitHub
[go: up one dir, main page]

Skip to content

Added Collaborator, Contributor and Repository.collaborators(affiliation) #731

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

AndreasBackx
Copy link
Contributor
@AndreasBackx AndreasBackx commented Sep 18, 2017

See #730 for some background information. This still fails 1 test because the cassette Repository_collaborators.json needs to be updated with the permissions as it somehow does not contain that information. The GitHub API does say that it should be there, but the recording is from 2014 so perhaps it wasn't returned back then.

Note that I have currently put the named parameter affiliation at the front of the arguments in Repository.collaborators. I did this to be in line with the other similar iterators. This can be moved to the back, but I assume some backwards-incompatible changes are fine for 1.0.0?

This uses separate classes for the specific User object uses as I understood the idea was from #670.

@AndreasBackx
Copy link
Contributor Author
AndreasBackx commented Apr 4, 2018

@sigmavirus24 any chance this gets looked at?

@sigmavirus24
Copy link
Owner

@AndreasBackx I'd be happy to give this a look. Would you mind rebasing this to merge cleanly?

@AndreasBackx
Copy link
Contributor Author
AndreasBackx commented Apr 6, 2018

I will, I'm currently not at my apartment for a few days so I might not be able to get to it this week. I'll rebase when I get back to my apartment, I hope to be back in a couple days.

omgjlk
omgjlk previously requested changes Apr 6, 2018
Copy link
Collaborator
@omgjlk omgjlk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple comments inline. Also I'd like to know what the right method is to go from having a Collaborator object and turning it into a User object.

@@ -524,17 +524,24 @@ def code_frequency(self, number=-1, etag=None):
url = self._build_url('stats', 'code_frequency', base_url=self._api)
return self._iter(int(number), url, list, etag=etag)

def collaborators(self, number=-1, etag=None):
def collaborators(self, affiliation='all', number=-1, etag=None):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The affiliations parameter should be documented here.

"""
url = self._build_url('collaborators', base_url=self._api)
return self._iter(int(number), url, users.ShortUser, etag=etag)
affiliations = {'outside', 'direct', 'all'}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a static list, not sure it belongs defined in this function or if it should be defined somewhere more global. That's likely a project preference thing, I defer to @sigmavirus24 .

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eh. I've waffled on this before. I think we do something similar in other places. I've wondered about having a github3.constants or (github3._constants) but it never felt important enough, honestly.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also toyed with some decorators that would do strong validation of the parameters and what's passed in to the function but that turned out to be way too much work.

Copy link
Contributor Author
@AndreasBackx AndreasBackx Apr 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can create an enum Affiliation perhaps with uppercase choices for each: Affiliation.OUTSIDE. You can then do list(Affiliation) for a list of all of them (though it'll give a list of enums, not their values). Maybe something along those lines could be adopted for other stuff as well. I don't really mind here. Tell me what to do for the constants here, and it'll get done.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need to tackle this @AndreasBackx. I think this is a murky corner for a library that supports Py2 and Py3. If we were Py3 only, I'd go whole-hog on using an Enum. Relying on the enum34 backport, however, has its own issues, I've found, and isn't worth the headache for end users right now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, I've been working exclusively in Python 3 so I've been forgetting about the Python 2 support as of late. Are there any plans to drop Python 2 support in the future?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing firm. Maybe later this year. Maybe next year.

This represents a user as a collaborator of a :class:`Repository`.
This adds permission information of the user to the repository.

.. versionadded:: 1.0.0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This version is a bit behind now.

@@ -0,0 +1,33 @@
from ..users import _User
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there reason to not just put these classes in github3.users?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No reason at all, preference perhaps. It'll get changed.

Copy link
Contributor Author
@AndreasBackx AndreasBackx Apr 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wait, now that I think about it. The reason I put it in github3.repos.users instead of github3.users is because I assumed that was implied in issue #670. As a collaborator's endpoint is /repos/:owner/:repo/collaborators. They belong to the repo so I thought it would be good to put those in github3.repos.users instead. Regardless though, tell me what you think is best.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's precedence for both decisions. I think we already have Contributor in github3.users so moving Collaborator in there too probably wouldn't hurt.

"""
url = self._build_url('collaborators', base_url=self._api)
return self._iter(int(number), url, users.ShortUser, etag=etag)
affiliations = {'outside', 'direct', 'all'}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eh. I've waffled on this before. I think we do something similar in other places. I've wondered about having a github3.constants or (github3._constants) but it never felt important enough, honestly.

"""
url = self._build_url('collaborators', base_url=self._api)
return self._iter(int(number), url, users.ShortUser, etag=etag)
affiliations = {'outside', 'direct', 'all'}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also toyed with some decorators that would do strong validation of the parameters and what's passed in to the function but that turned out to be way too much work.

"'direct', or 'all' (default 'all')."
)
params = {'affiliation': affiliation}
return self._iter(int(number), url, Collaborator, params, etag=etag)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think as a rule we've switched to importing modules and not classes, so these shouldn't be the exception.

affiliations = {'outside', 'direct', 'all'}
if affiliation not in affiliations:
raise ValueError(
"Invalid affiliation parameter passed, must be 'outside', "
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should format the given affiliation into this to make it easier for debugging. Perhaps:

("Invalid affiliation value {!r} parameter passed, must be 'outside',"
 "'direct', or 'all' (defaults to 'all').").format(affiliation)

)

def test_collaborators_valid_affiliation(self):
"""
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know we're not great at this elsewhere in the tests, but I'm hoping to get our doc-strings cleaned up soon. I tried to do so in the code itself. I'm going to target the tests next and it'd be good to do less work 😉

Could you substitute something like

"""Verify we can list collaborator with a valid affiliation.

Let's ensure that our affiliation validation works.
"""

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably a mistake on my end. I usually follow the same principle.

@sigmavirus24
Copy link
Owner

Gave this a review pass as well. There's no rush to fix it up. This looks really close to perfect. Thanks @AndreasBackx for putting the work into doing this. 🎉

@AndreasBackx
Copy link
Contributor Author
AndreasBackx commented Apr 7, 2018

Alright, I've looked over the comments and I'll fix what needs to be fixed and I've replied to your questions. I'll try to get to it the coming days. Thanks for taking the time to review the PR.

@sigmavirus24
Copy link
Owner

Oh, and regarding how Contributor and Collaborator turn into a User, I think the answer lies in the examples of how ShortUser becomes a User(i.e., setting _refresh_to)

@AndreasBackx
Copy link
Contributor Author
AndreasBackx commented Apr 8, 2018

I'm rebasing right now and see that Contributor has the attribute contributions, but it seems to be documented as contributions_count. Is the documentation wrong or should the attribute be renamed?

A User has got:

self.followers_count = user['followers']

And the Contributor has got:

class Contributor(_User):
    """Object for the specialized representation of a contributor.

    When retrieving a repository's contributors, GitHub returns the same
    information as a :class:`~github3.users.ShortUser` with an additional
    attribute:

    .. versionadded:: 1.0.0

        This class was added in version 1.0.0

    .. attribute:: contributions_count

        The number of contributions a contributor has made to the repository

    """

    class_name = 'Contributor'

    def _update_attributes(self, contributor):
        super(Contributor, self)._update_attributes(contributor)
        self.contributions = contributor['contributions']

Should it become:

self.contributions_count = contributor['contributions']

I thought I'd post it here and include it in the PR perhaps, it seems a bit silly to make a new PR/issue just for this.

@AndreasBackx AndreasBackx force-pushed the feature/collaborators branch from 15af1b9 to ff8501a Compare April 8, 2018 11:52
…ion).

See sigmavirus24#730 for some background information.

Note that I have currently put the named parameter `affiliation` at the front
of the arguments in `Repository.collaborators`. I did this to be in line with
the other similar iterators. This can be moved to the back, but I assume some
backwards-incompatible changes are fine for 1.0.0?

This uses separate classes for the specific User object uses as I understood
the idea was from sigmavirus24#670.
@AndreasBackx AndreasBackx force-pushed the feature/collaborators branch from ff8501a to 17de8b8 Compare April 8, 2018 12:00
@AndreasBackx
Copy link
Contributor Author
AndreasBackx commented Apr 8, 2018

I've rebased the PR following your feedback. I haven't changed Contributor.contributions to Contributor.contributions_count like I mentioned in my previous comment.

I've added the ability to refresh the Collaborator as well like @sigmavirus24 mentioned and added it to the docs. I assumed that this will be in 1.0.3 so I've used that version in the version changes/additions.

I had to update the cassette Repository_collaborators, but because I don't have push access to this repository, which is used in the tests and is required by the GitHub API for retrieving the collaborators. I changed it temporarily to my PR's develop branch, ran the tests, and changed the username from AndreasBackx to sigmavirus24. It shouldn't make a difference for the tests that are performed using it or in the future I assume.

Let me know if I missed something.

PS: The AppVeyor build seems to use the old commit, could someone run the latest? I assume Travis is running as I am typing this, but I can't check as it seems to be set to private (which I assume is in case of secrets leaking?). I tested everything successfully locally.

@sigmavirus24
Copy link
Owner

It should be contributions_count that's what I intended it to be at least :)

Reverted Repository_collaborators.json, as the base64 in it still contained
the wrong URLs for the integration tests. They need to be regenerated by
someone who has push access to the repository.
@sigmavirus24
Copy link
Owner

Let me try closing and re-opening this to trigger builds. Travis was broken so let's see if this fixes AppVeyor too.

@sigmavirus24 sigmavirus24 reopened this Apr 8, 2018
@AndreasBackx
Copy link
Contributor Author
AndreasBackx commented Apr 8, 2018

I've reverted Repository_collaborators.json to its original state as the base64 strings in it contain the URLs to my repository. It needs to be regenerated by someone who has push access to this repository. I think I forgot to test the file after I changed everything, and it was failing because the library received my fork's URL instead of this repository's URL. But betamax had this repository's URL in the cassette so it failed.

I've also found another "bug" as you will in the tox config:

envlist = py{27,34,35,36,py},py{27,34,36}-flake8,docstrings

The envlist mentions a py36-flake8 environment, but that one does not exist so it falls back to py36 which then essentially gets run twice when running tox.

@sigmavirus24
Copy link
Owner

I re-recorded the cassette and pushed it to your branch. @AndreasBackx can you send another PR to add that environment to our tox.ini?

@sigmavirus24 sigmavirus24 dismissed omgjlk’s stale review April 8, 2018 15:42

All feedback seems to have been addressed. Thanks for reviewing this

@sigmavirus24
Copy link
Owner

I pushed some extra changes here as I noticed some things I didn't quite like about the docstrings.

@sigmavirus24 sigmavirus24 merged commit 05ed0c6 into sigmavirus24:develop Apr 8, 2018
@sigmavirus24
Copy link
Owner

🎉 Thanks @AndreasBackx!

@AndreasBackx
Copy link
Contributor Author
AndreasBackx commented Apr 8, 2018

Regarding the environment change in tox.ini do I need to add it or do I need to change the py34-flake8 to py36-flake8? I doubt that we need 2 of those environments for Python 3?

PS: I accidentally checked tests/cassettes/Repository_collaboratorsold.json in. That was my mistake.

@sigmavirus24
Copy link
Owner

You can change py34 to py36 for Flake8. Just make sure you remove the py34 from the envlist.

And don't worry about checking in the old cassette. It's all sorted 😄

@AndreasBackx
Copy link
Contributor Author

Will do.

I know, I saw the diff which is when I realised that I had accidentally checked it in.

AndreasBackx added a commit to AndreasBackx/github3.py that referenced this pull request Apr 9, 2018
sigmavirus24 pushed a commit that referenced this pull request Apr 9, 2018
This also requires us to be slightly more explicit with our Travis configuration.

See discussion on gh-731.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
0