Coder Social home page Coder Social logo

box.py's People

Contributors

aaylward avatar echelon avatar emiller avatar k8n avatar prexer avatar samkuehn avatar tals avatar tsanch3z avatar ttreuthardt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

box.py's Issues

content_modified_at in upload_file

Hi,

I should probably do a pull request for this one, but I haven't cloned this repository "properly" yet (new to the whole git thing). I've just been modifying a local copy of client.py as needed.

So, to the point: I think the upload_file function should have a content_modified_at argument, same as the overwrite_file function. This could be important in any bi-directional sync type scenario, where it is important to keep the remote file's "last modified" time the same as that of the one uploaded so that a decision about the sync direction could be made in the future.

I can do a proper pull request for this if necessary. Just let me know how :)

Thanks.

Asynchronous requests with grequests?

grequests can be dropped in for asynchronous API requests with gevent:
sprin/box.py@1cb1c30

You probably don't want to drag gevent/grequests in as a hard deps, but perhaps grequests can be imported conditionally?

This change enabled me do recursive operations almost two orders of magnitude faster, eventually running into rate-limiting. However, the pool can be used to limit the number of concurrent requests to avoid rate-limiting.

Here is recursive folder walking and folder creation done asynchronously.

Aside: If the those recursive functions are of interest to integrate into box.py, I'd be happy to make it more general and provide tests.

Thumbnail retrieval

I am having some troubles retrieving a file's thumbnail

the get_thumbnail function return the raw field of the server's response and I couldn't find a way to get its content. the read() method doesn't return anything even with a specified length and a call to the data field neither.

The only workaround I have found so far is to return the complete response object in get_thumbnail so I can get the thumbnail using the content or text fields.

Am I missing something about this function usage ?

Allow download_file to return non-raw socket response

Hi,

So, I'm unsure yet if this is actually an issue, but here goes. I'm kinda new to working with HTTP requests and downloading stuff etc. I was trying to figure out how to download large files in a "somewhat-non-blocking" fashion so that I can have a progress bar and I stumbled onto this page (http://www.python-requests.org/en/latest/user/quickstart/?highlight=iter_content). I was able to do what I needed by using the raw response example given, but the page suggests that using Response.iter_content on the "not-raw" response is better (I imagine it does error checking but I'm not sure).

The download_file function returns a raw, but I changed my local copy of client.py so that it doesn't and I can use the iter_content method for downloading files. Would it make sense to add an option to the function so that it can return either? Also, what are the advantages for using iter_content?

Thanks.

share_link api

The share_link() method is working when access=ShareAccess.OPEN. However when access=ShareAccess. COLLABORATORS, it is giving status 400

{"type":"error","status":400,"code":"bad_request","context_info":{"errors":[{"reason":"invalid_parameter","name":"shared_link_permissions","message":"Invalid value 'download => 1'."}]}

ValueError thrown when running the example from the README

When I run the "upload" example from the README:

>>> from box import BoxClient
>>> from StringIO import StringIO
>>> client = BoxClient('<valid access token>')
>>> client.upload_file('hello.txt', StringIO('hello world'))

The following traceback is thrown:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/lib/python2.7/site-packages/box/client.py", line 531, in upload_file
    result = self._request("post", "files/content", endpoint="upload", data=form, files={filename: fileobj})
  File "/lib/python2.7/site-packages/box/client.py", line 304, in _request
    response = requests.request(method, url, params=params, data=data, headers=headers, **kwargs)
  File "/lib/python2.7/site-packages/requests-1.2.3-py2.7.egg/requests/api.py", line 44, in request
    return session.request(method=method, url=url, **kwargs)
  File "/lib/python2.7/site-packages/requests-1.2.3-py2.7.egg/requests/sessions.py", line 324, in request
    prep = req.prepare()
  File "/lib/python2.7/site-packages/requests-1.2.3-py2.7.egg/requests/models.py", line 225, in prepare
    p.prepare_body(self.data, self.files)
  File "/lib/python2.7/site-packages/requests-1.2.3-py2.7.egg/requests/models.py", line 385, in prepare_body
    (body, content_type) = self._encode_files(files, data)
  File "/lib/python2.7/site-packages/requests-1.2.3-py2.7.egg/requests/models.py", line 99, in _encode_files
    fields = to_key_val_list(data or {})
  File "/lib/python2.7/site-packages/requests-1.2.3-py2.7.egg/requests/utils.py", line 136, in to_key_val_list
    raise ValueError('cannot encode objects that are not 2-tuples')
ValueError: cannot encode objects that are not 2-tuples

Long Poll Error

Using the example code provided here, I am attempting to test the long poll functionality. I keep getting the following error:

Traceback (most recent call last):
  File "box_long_poll.py", line 5, in <module>
    position = client.long_poll_for_events() # this will block until there are new events
  File "/usr/local/lib/python2.7/dist-packages/box/client.py", line 694, in long_poll_for_events
    stream_position = cursor['next_stream_position']
TypeError: 'Response' object has no attribute '__getitem__'

There seems to be an issue uploading files with non-ascii character in their names

Here is a trace (upload_file executed via box.py) that fails with "status":400,"code":"invalid_request_parameters":

POST /api/2.0/files/content HTTP/1.1
Host: upload.box.com
Content-Length: 47237
Accept-Encoding: gzip, deflate, compress
Accept: */*
User-Agent: python-requests/2.2.1 CPython/2.7.5 Darwin/13.1.0
Content-Type: multipart/form-data; boundary=c5a8408bda51429ba5871377731fc678
Authorization: Bearer ACCESS_TOKEN

--c5a8408bda51429ba5871377731fc678
Content-Disposition: form-data; name="parent_id"

1673257278
--c5a8408bda51429ba5871377731fc678
Content-Disposition: form-data; name*=utf-8''S%C3%A9vigny.pdf; filename*=utf-8''S%C3%A9vigny.pdf

Here is a trace from an equivalent openration via curl:

0000: POST /api/2.0/files/content HTTP/1.1
0026: User-Agent: curl/7.30.0
003f: Host: upload.box.com
0055: Accept: */*
0062: Authorization: Bearer ACCESS_TOKEN
009a: Content-Length: 43177
00b1: Expect: 100-continue
00c7: Content-Type: multipart/form-data; boundary=--------------------
0107: --------37edc5e8d7c9
011d: 
<= Recv header, 23 bytes (0x17)
0000: HTTP/1.1 100 Continue
=> Send data, 161 bytes (0xa1)
0000: ------------------------------37edc5e8d7c9
002c: Content-Disposition: form-data; name="filename"; filename="Se..v
006c: igny.pdf"
0077: Content-Type: application/octet-stream
009f: 
=> Send data, 16384 bytes (0x4000)

Seems Box Content API is not liking RFC 2231-encoded file names. More related discussion on this. And a hack-around?

I'm not sure yet what to tell requests library to send filename unencoded.

finish_authenticate_v2 error

I have an issue with authenticating the user using the 'finish_authenticate_v2' function. Specifically, 'request.REQUEST['code']' is not working. What library are you importing? Assuming the library is imported correctly, will the 'code' from the url redirection be transferred automatically to request.REQUEST['code']?

Currently, if I replace request.REQUEST['code'] with the actual code, I can get obtain my access token. However, I do not want to hardcode anything.

I am terribly new at this, sorry if this is such an easy problem.

I have an stackoverflow post as well: http://stackoverflow.com/questions/20339261/how-to-grab-the-authorization-code-from-url-to-get-token-in-box-using-python/20339480?noredirect=1#20339480

Deletion related APIs should be executed with "raw=True"

According to the documentation, deletion API will return a "empty 204 response", thus without raw=True, response.json() from client._request raises exception.

JSONDecodeError: No JSON object could be decoded: line 1 column 0 (char 0)

The delete_folder API does issue a raw=True request, but delete_file doesn't.

def delete_file(self, file_id, etag=None):
      """
      Discards a file to the trash.

      Args:
           - etag: (optional) If specified, the file will only be deleted if
                its etag matches the parameter
      """

      headers = {}
      if etag:
          headers['If-Match'] = etag

      self._request("delete", 'files/{}'.format(file_id), headers=headers)

I'd like to fix this, actually I've cloned this repo. But I want to do more. So I look into the test cases, found that mocked_response might "mocked" too much, I mean it just assume we always can get a valid response from the API server, when there is no content available, we assume None returned. But that's not the real case. Empty content is not accepted by both json or simplejson.

So I patched a little

 diff --git a/tests/__init__.py b/tests/__init__.py
 index eb87755..ab2f2ce 100644
 --- a/tests/__init__.py
 +++ b/tests/__init__.py
 @@ -1,5 +1,9 @@
  from StringIO import StringIO
  from datetime import tzinfo, timedelta, datetime
 +try:
 +    import simplejson as json
 +except:
 +    import json as json

  from flexmock import flexmock

 @@ -45,4 +49,9 @@ utc = UTC()


  def mocked_response(content=None, status_code=200, headers=None):
 -    return flexmock(ok=status_code < 400, status_code=status_code, json=lambda: content, raw=content, text=content, headers=headers)
 +    if content is None:
 +        content = ''
 +    if not isinstance(content, basestring):
 +        content = json.dumps(content)
 +
 +    return flexmock(ok=status_code < 400, status_code=status_code, json=lambda: json.loads(content), raw=content, text=content, headers=headers)

Of cause some cases are broken, and some of them should be. But some broken ones like

def test_get(self):
    client = self.make_client("get", "foo", params={'arg': 'value'}, crap=1)
    client._request('get', 'foo', {'arg': 'value'}, crap=1)

def test_post_dict(self):
    expected_data = {'arg': 'value'}
    client = self.make_client("post", "foo", data=expected_data, crap=1)
    actual_response = client._request('post', 'foo', data=expected_data, crap=1)
    self.assertEqual(None, actual_response)

def test_post_data(self):
    expected_data = "mooooo"
    client = self.make_client("post", "foo", data=expected_data, crap=1)
    actual_response = client._request('post', 'foo', data=expected_data, crap=1)
    self.assertEqual(None, actual_response)

def test_put_dict(self):
    expected_data = {'arg': 'value'}
    client = self.make_client("put", "foo", data=expected_data, crap=1)
    actual_response = client._request('put', 'foo', data=expected_data, crap=1)
    self.assertEqual(None, actual_response)

I just don't get why we need these cases, which issuing non-exist API path "foo". It won't be hard to just look through the source code and patch raw=True if needed, but I think we better make these test cases more robust.

Which way should we take to fix this problem? Simply add raw=True?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.