-
Notifications
You must be signed in to change notification settings - Fork 219
Add new Recents API to client #210
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
Conversation
|
Verified that @josephroque has signed the CLA. Thanks for the pull request! |
| response_object=response, | ||
| ) | ||
|
|
||
| @api_call |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It appears this endpoint uses marker based paging, not limit/offset.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 waiting on #212 to rebase
| `Iterable` of `unicode` | ||
| :returns: | ||
| A list of the user's recently accessed items. | ||
| :rtype: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this returns a list of RecentItem, right?
| The index at which to start returning items. | ||
| :type offset: | ||
| `int` | ||
| :param fields: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mention that the fields apply to the recent item object, not to the underlying file or folder.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, these do apply to the underlying file or folder. I'll mention that. The recent_item type always has the same fields, but returns the 'mini' file/folder format by default, so this is to request more fields. It's similarly unclear in the API documentation, but that is what it does in practice. I'll update this to be more clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, cool.
| A list of the user's recently accessed items. | ||
| :rtype: | ||
| `list` of :class:`Item` | ||
| """ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can be self.get_url('recent_items')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything else in the file follows the format used here. Should I still change it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Up to you, I guess. Most of the other things in this file predate being able to use self.get_url
boxsdk/pagination/page.py
Outdated
| item = item_class( | ||
| session=self._session, | ||
| object_id=item_json['id'], | ||
| object_id=item_json['id'] if 'id' in item_json else None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that RecentItem is not a subclass of BaseObject because most of the functionality provided by BaseObject does not apply to to recent items (o way to GET individual recent items, no way to update). Finally, recent items from the API do not have unique IDs associated with them, so there's no way to get item_json['id']
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can do something like this:
item_class = self._translator.translate(item_json['type'])
kwargs = {}
if issubclass(item_class, BaseEndpoint):
kwargs['session'] = self._session
if issubclass(item_class, BaseObject):
kwargs['object_id'] = item_json['id'] if 'id' in item_json else None
item = item_class(response_object=item_json, **kwargs)It's not great, but it should work, for now. Eventually we'll make something nicer than this for #140 .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is what's going to be necessary - solves the **kwargs in RecentItem as well.
| response_object=response, | ||
| ) | ||
|
|
||
| @api_call |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add **kwargs, and pass that to MarkerBasedObjectCollection. And then remove return_full_pages=True below, since that's a decision that the client, not the SDK, should make.
Depending on your personal preference, you could remove limit, marker, and fields, and leave them all for **kwargs. Or you can leave it as-is.
boxsdk/client/client.py
Outdated
| limit=limit, | ||
| fields=fields, | ||
| marker=marker, | ||
| return_full_pages=True, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if this is necessary, I believe it defaults to False.
boxsdk/object/recent_item.py
Outdated
| response_object=item, | ||
| ) | ||
|
|
||
| def get_url(self, *args): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this needed? As you said, this isn't a BaseObject, so we'll never be calling API endpoints for this object.
boxsdk/object/recent_item.py
Outdated
|
|
||
| _item_type = 'recent_item' | ||
|
|
||
| def __init__(self, session, response_object=None, **kwargs): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't accept **kwargs unless we're willing to do something with it.
Doing this is just a hack around the fact that we're passing object_id to it..
We should solve that problem a different way.
And if we remove **kwargs, then you can actually just remove this method override altogether, since it isn't doing anything other than calling super.
boxsdk/pagination/page.py
Outdated
| item = item_class( | ||
| session=self._session, | ||
| object_id=item_json['id'], | ||
| object_id=item_json['id'] if 'id' in item_json else None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can do something like this:
item_class = self._translator.translate(item_json['type'])
kwargs = {}
if issubclass(item_class, BaseEndpoint):
kwargs['session'] = self._session
if issubclass(item_class, BaseObject):
kwargs['object_id'] = item_json['id'] if 'id' in item_json else None
item = item_class(response_object=item_json, **kwargs)It's not great, but it should work, for now. Eventually we'll make something nicer than this for #140 .
| def marker_id(): | ||
| return 'marker_1' | ||
|
|
||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Won't this break if it is a module fixture? Because the Mock will retain its call spec between tests if we do this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This user_response object was pre-existing, git just reports me as adding it. I added the lines above, with the @pytext.fixture from there. So for the comment on scope below, I followed suit from this line you're commenting on here. Additionally, I believe most of these fixtures are used in a read-only sense, so reuse of them in the tests is inconsequential.
| return mock_network_response | ||
|
|
||
|
|
||
| @pytest.fixture(scope='module') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, this doesn't seem like something that should be module scoped.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above
test/unit/client/test_client.py
Outdated
| 'entries': [ | ||
| {'type': 'recent_item', 'item': {'type': 'file', 'id': file_id}} | ||
| ], | ||
| 'next_marker': marker_id, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Providing a next_marker implies that there are more results coming. So if you try paging, it'll try to make a second API call, which doesn't seem like what you want.
…tests to match new behavior
| "item": {"type": "file", "id": mock_object_id} | ||
| }) | ||
| assert recent_item['type'] == 'recent_item' | ||
| assert recent_item.item.object_id == mock_object_id |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you also assert recent_item.item.session is mock_box_session?
| response_object=response, | ||
| ) | ||
|
|
||
| @api_call |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In docstring, document that **kwargs are passed to MarkerBasedObjectCollection.
We could also call this **collection_kwargs or **paging_kwargs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, I was going to do this, but noticed it wasn't done that way somewhere else, so I thought it might be like, a standard.
See: https://developer.box.com/v2.0/reference#recent-item-object Use the Client to retrieve a user's recently accessed items on Box. `RecentItem` class allows the translator to correctly instantiate the item returned by the API, which has the field `type='recent_item'`. This provides some additional fields, and access to the underlying File/Folder as the property `RecentItem.item`
See: https://developer.box.com/v2.0/reference#recent-item-object
Use the Client to retrieve a user's recently accessed items on Box.
RecentItemclass allows the translator to correctly instantiate the item returned by the API, which has the fieldtype='recent_item'. This provides some additional fields, and access to the underlying File/Folder as the propertyRecentItem.item