Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
4e5f9d5
Add a Cloneable interface
Jul 26, 2016
08920dc
Make BaseEndpoint implement Cloneable interface
Jul 26, 2016
4c513f6
Add api_call_decorator
Jul 28, 2016
e630272
- Make BoxSession store default network request args
Jul 28, 2016
7adfe04
Make all smart objects cloneable and use api_call decorator
Jul 28, 2016
db86f40
Use api_call decorator on all API call methods
Jul 30, 2016
0496cec
Add Item unit test with api_call decorator.
Jul 31, 2016
7ed337d
Add functional tests that test cloning.
Jul 31, 2016
9eef7e8
Clean up.
Jul 31, 2016
434d65e
Add api_call decorator to BaseObject's delete method.
Jul 31, 2016
1ea2982
Move Cloneable to its own file.
Jul 31, 2016
8037373
Add api_call decorators in Client.
Jul 31, 2016
360fd71
Add api_call decorator more BaseObject methods.
Jul 31, 2016
aa85abb
Remove unnecessary api_call decorator.
Aug 1, 2016
6cc1aef
Add a Cloneable interface
Jul 26, 2016
299c3b4
Make BaseEndpoint implement Cloneable interface
Jul 26, 2016
124d8dd
Add api_call_decorator
Jul 28, 2016
a7e152a
- Make BoxSession store default network request args
Jul 28, 2016
a667568
Make all smart objects cloneable and use api_call decorator
Jul 28, 2016
5702999
Use api_call decorator on all API call methods
Jul 30, 2016
9aba4e9
Add Item unit test with api_call decorator.
Jul 31, 2016
f0febe2
Add functional tests that test cloning.
Jul 31, 2016
015ddeb
Clean up.
Jul 31, 2016
14f6f8a
Add api_call decorator to BaseObject's delete method.
Jul 31, 2016
f41d2d3
Move Cloneable to its own file.
Jul 31, 2016
b7f190f
Add api_call decorators in Client.
Jul 31, 2016
ac209cc
Add api_call decorator more BaseObject methods.
Jul 31, 2016
dfc335e
Remove unnecessary api_call decorator.
Aug 1, 2016
df59b66
Merge branch 'cloneable' of https://github.com/box/box-python-sdk int…
Aug 1, 2016
dcf58bd
Fix linter errors.
Aug 1, 2016
c1e5e6b
Remove unused imports.
Aug 1, 2016
030a262
Clean up.
Aug 9, 2016
7e7117b
Remove unnecessary constructor override.
Aug 16, 2016
53ca0a7
Fix merge conflicts.
Aug 16, 2016
84940e3
Response to review comments.
Aug 16, 2016
8c17203
Response to review comments.
Aug 16, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 24 additions & 30 deletions boxsdk/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@
from ..config import API
from ..session.box_session import BoxSession
from ..network.default_network import DefaultNetwork
from ..object.cloneable import Cloneable
Copy link
Contributor

Choose a reason for hiding this comment

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

alphabetize

from ..util.api_call_decorator import api_call
from ..object.search import Search
from ..object.events import Events
from ..util.shared_link import get_shared_link_header
from ..util.translator import Translator


class Client(object):
class Client(Cloneable):

def __init__(
self,
Expand All @@ -34,6 +36,7 @@ def __init__(
:type session:
:class:`BoxSession`
"""
super(Client, self).__init__()
network_layer = network_layer or DefaultNetwork()
self._oauth = oauth
self._network = network_layer
Expand All @@ -49,6 +52,16 @@ def auth(self):
"""
return self._oauth

@property
def session(self):
"""
Get the :class:`BoxSession` instance the client is using.

:rtype:
:class:`BoxSession`
"""
return self._session

def folder(self, folder_id):
"""
Initialize a :class:`Folder` object, whose box id is folder_id.
Expand Down Expand Up @@ -124,6 +137,7 @@ def collaboration(self, collab_id):
"""
return Translator().translate('collaboration')(session=self._session, object_id=collab_id)

@api_call
def users(self, limit=None, offset=0, filter_term=None):
"""
Get a list of all users for the Enterprise along with their user_id, public_name, and login.
Expand Down Expand Up @@ -160,6 +174,7 @@ def users(self, limit=None, offset=0, filter_term=None):
response_object=item,
) for item in response['entries']]

@api_call
def search(
self,
query,
Expand Down Expand Up @@ -246,6 +261,7 @@ def group_membership(self, group_membership_id):
object_id=group_membership_id,
)

@api_call
def groups(self):
"""
Get a list of all groups for the current user.
Expand All @@ -265,6 +281,7 @@ def groups(self):
response_object=item,
) for item in response['entries']]

@api_call
def create_group(self, name):
"""
Create a group with the given name.
Expand Down Expand Up @@ -292,6 +309,7 @@ def create_group(self, name):
response_object=response,
)

@api_call
def get_shared_item(self, shared_link, password=None):
"""
Get information about a Box shared link. https://box-content.readme.io/reference#get-a-shared-item
Expand Down Expand Up @@ -322,6 +340,7 @@ def get_shared_item(self, shared_link, password=None):
response_object=response,
)

@api_call
def make_request(self, method, url, **kwargs):
"""
Make an authenticated request to the Box API.
Expand All @@ -343,6 +362,7 @@ def make_request(self, method, url, **kwargs):
"""
return self._session.request(method, url, **kwargs)

@api_call
def create_user(self, name, login=None, **user_attributes):
"""
Create a new user. Can only be used if the current user is an enterprise admin, or the current authorization
Expand Down Expand Up @@ -375,35 +395,9 @@ def create_user(self, name, login=None, **user_attributes):
response_object=response,
)

def as_user(self, user):
"""
Returns a new client object with default headers set up to make requests as the specified user.

:param user:
The user to impersonate when making API requests.
:type user:
:class:`User`
"""
return self.__class__(self._oauth, self._network, self._session.as_user(user))

def with_shared_link(self, shared_link, shared_link_password):
"""
Returns a new client object with default headers set up to make requests using the shared link for auth.

:param shared_link:
The shared link.
:type shared_link:
`unicode`
:param shared_link_password:
The password for the shared link.
:type shared_link_password:
`unicode`
"""
return self.__class__(
self._oauth,
self._network,
self._session.with_shared_link(shared_link, shared_link_password),
)
def clone(self, session=None):
"""Base class override."""
return self.__class__(self._oauth, self._network, session or self._session)

def get_url(self, endpoint, *args):
"""
Expand Down
43 changes: 20 additions & 23 deletions boxsdk/object/base_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

from __future__ import unicode_literals, absolute_import

from .cloneable import Cloneable

class BaseEndpoint(object):

class BaseEndpoint(Cloneable):
"""A Box API endpoint."""

def __init__(self, session, **kwargs):
Expand All @@ -20,6 +22,16 @@ def __init__(self, session, **kwargs):
super(BaseEndpoint, self).__init__(**kwargs)
self._session = session

@property
def session(self):
"""
Get the :class:`BoxSession` instance the object is using.

:rtype:
:class:`BoxSession`
"""
return self._session

def get_url(self, endpoint, *args):
"""
Return the URL used to access the endpoint.
Expand All @@ -38,28 +50,13 @@ def get_url(self, endpoint, *args):
# pylint:disable=no-self-use
return self._session.get_url(endpoint, *args)

def as_user(self, user):
"""
Returns a new endpoint object with default headers set up to make requests as the specified user.

:param user:
The user to impersonate when making API requests.
:type user:
:class:`User`
def clone(self, session=None):
"""
return self.__class__(self._session.as_user(user))
Returns a copy of this cloneable object using the specified session.

def with_shared_link(self, shared_link, shared_link_password):
"""
Returns a new endpoint object with default headers set up to make requests using the shared link for auth.

:param shared_link:
The shared link.
:type shared_link:
`unicode`
:param shared_link_password:
The password for the shared link.
:type shared_link_password:
`unicode`
:param session:
The Box session used to make requests.
:type session:
:class:`BoxSession`
"""
return self.__class__(self._session.with_shared_link(shared_link, shared_link_password))
return self.__class__(session or self._session)
14 changes: 7 additions & 7 deletions boxsdk/object/base_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from .base_endpoint import BaseEndpoint
from .base_api_json_object import BaseAPIJSONObject
from ..util.translator import Translator
from ..util.api_call_decorator import api_call


class BaseObject(BaseEndpoint, BaseAPIJSONObject):
Expand Down Expand Up @@ -62,6 +63,7 @@ def object_id(self):
"""
return self._object_id

@api_call
def get(self, fields=None, headers=None):
"""
Get information about the object, specified by fields. If fields is None, return the default fields.
Expand All @@ -84,6 +86,7 @@ def get(self, fields=None, headers=None):
box_response = self._session.get(url, params=params, headers=headers)
return self.__class__(self._session, self._object_id, box_response.json())

@api_call
def update_info(self, data, params=None, headers=None, **kwargs):
"""Update information about this object.

Expand Down Expand Up @@ -127,6 +130,7 @@ def update_info(self, data, params=None, headers=None, **kwargs):
response_object=response,
)

@api_call
def delete(self, params=None, headers=None):
""" Delete the object.

Expand Down Expand Up @@ -212,14 +216,10 @@ def _paging_wrapper(self, url, starting_index, limit, factory=None):
if current_index >= response['total_count']:
break

def as_user(self, user):
""" Base class override. """
return self.__class__(self._session.as_user(user), self._object_id, self._response_object)

def with_shared_link(self, shared_link, shared_link_password):
""" Base class override. """
def clone(self, session=None):
"""Base class override."""
return self.__class__(
self._session.with_shared_link(shared_link, shared_link_password),
session or self._session,
self._object_id,
self._response_object,
)
54 changes: 54 additions & 0 deletions boxsdk/object/cloneable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# coding: utf-8

from __future__ import unicode_literals, absolute_import


class Cloneable(object):
"""
Cloneable interface to be implemented by endpoint objects that should have ability to be cloned, but with a
different session member if desired.
"""

def as_user(self, user):
"""
Returns a new endpoint object with default headers set up to make requests as the specified user.
:param user:
The user to impersonate when making API requests.
:type user:
:class:`User`
"""
return self.clone(self.session.as_user(user))

def with_shared_link(self, shared_link, shared_link_password):
"""
Returns a new endpoint object with default headers set up to make requests using the shared link for auth.
Copy link
Contributor

Choose a reason for hiding this comment

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

Sphinx needs blank lines between the title, and the rest of the docstring.

This is fine for now, but we should probably do a test run of sphinx, and fix all the errors, before doing a release.

:param shared_link:
The shared link.
:type shared_link:
`unicode`
:param shared_link_password:
The password for the shared link.
:type shared_link_password:
`unicode`
"""
return self.clone(self.session.with_shared_link(shared_link, shared_link_password))

def clone(self, session=None):
"""
Returns a copy of this cloneable object using the specified session.
:param session:
The Box session used to make requests.
:type session:
:class:`BoxSession`
"""
raise NotImplementedError

@property
def session(self):
"""
Return the Box session being used to make requests.
:rtype:
:class:`BoxSession`
"""
raise NotImplementedError
4 changes: 3 additions & 1 deletion boxsdk/object/collaboration.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# coding: utf-8

from __future__ import unicode_literals
from __future__ import unicode_literals, absolute_import

from boxsdk.object.base_object import BaseObject
from boxsdk.util.text_enum import TextEnum
from ..util.api_call_decorator import api_call


class CollaborationRole(TextEnum):
Expand Down Expand Up @@ -32,6 +33,7 @@ class Collaboration(BaseObject):
_item_type = 'collaboration'

# pylint:disable=arguments-differ
@api_call
def update_info(self, role=None, status=None):
"""Edit an existing collaboration on Box

Expand Down
6 changes: 6 additions & 0 deletions boxsdk/object/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from six import with_metaclass

from .base_endpoint import BaseEndpoint
from ..util.api_call_decorator import api_call
from ..util.enum import ExtendableEnumMeta
from ..util.lru_cache import LRUCache
from ..util.text_enum import TextEnum
Expand Down Expand Up @@ -57,6 +58,7 @@ def get_url(self, *args):
"""Base class override."""
return super(Events, self).get_url('events', *args)

@api_call
def get_events(self, limit=100, stream_position=0, stream_type=UserEventsStreamType.ALL):
"""
Get Box events from a given stream position for a given stream type.
Expand Down Expand Up @@ -95,6 +97,7 @@ def get_events(self, limit=100, stream_position=0, stream_type=UserEventsStreamT
response['entries'] = [Translator().translate(item['type'])(item) for item in response['entries']]
return response

@api_call
def get_latest_stream_position(self, stream_type=UserEventsStreamType.ALL):
"""
Get the latest stream position. The return value can be used with :meth:`get_events` or
Expand Down Expand Up @@ -136,6 +139,7 @@ def _get_all_events_since(self, stream_position, stream_type=UserEventsStreamTyp
if len(events) < 100:
return

@api_call
def long_poll(self, options, stream_position):
"""
Set up a long poll connection at the specified url.
Expand Down Expand Up @@ -163,6 +167,7 @@ def long_poll(self, options, stream_position):
)
return long_poll_response

@api_call
def generate_events_with_long_polling(self, stream_position=None, stream_type=UserEventsStreamType.ALL):
"""
Subscribe to events from the given stream position.
Expand Down Expand Up @@ -212,6 +217,7 @@ def generate_events_with_long_polling(self, stream_position=None, stream_type=Us
else:
break

@api_call
def get_long_poll_options(self, stream_type=UserEventsStreamType.ALL):
"""
Get the url and retry timeout for setting up a long polling connection.
Expand Down
Loading