Giter VIP home page Giter VIP logo

onedrive-sdk-python's Introduction

Getting started with the OneDrive SDK for Python


Build status

Installation

Once you've downloaded the OneDrive SDK for Python, open a command prompt and type the following to install it:

pip install onedrivesdk

Next, include the SDK in your Python project by adding:

import onedrivesdk

Authentication

OneDrive

To interact with the OneDrive API, your app must authenticate. You can use the following code sample to do so.

import onedrivesdk

redirect_uri = 'http://localhost:8080/'
client_secret = 'your_client_secret'
client_id='your_client_id'
api_base_url='https://api.onedrive.com/v1.0/'
scopes=['wl.signin', 'wl.offline_access', 'onedrive.readwrite']

http_provider = onedrivesdk.HttpProvider()
auth_provider = onedrivesdk.AuthProvider(
    http_provider=http_provider,
    client_id=client_id,
    scopes=scopes)

client = onedrivesdk.OneDriveClient(api_base_url, auth_provider, http_provider)
auth_url = client.auth_provider.get_auth_url(redirect_uri)
# Ask for the code
print('Paste this URL into your browser, approve the app\'s access.')
print('Copy everything in the address bar after "code=", and paste it below.')
print(auth_url)
code = raw_input('Paste code here: ')

client.auth_provider.authenticate(code, redirect_uri, client_secret)

The above code requires copy-pasting into your browser and back into your console. If you want to remove some of that manual work, you can use the helper class GetAuthCodeServer. That helper class spins up a webserver, so this method cannot be used on all environments.

import onedrivesdk
from onedrivesdk.helpers import GetAuthCodeServer

redirect_uri = 'http://localhost:8080/'
client_secret = 'your_app_secret'
scopes=['wl.signin', 'wl.offline_access', 'onedrive.readwrite']

client = onedrivesdk.get_default_client(
    client_id='your_client_id', scopes=scopes)

auth_url = client.auth_provider.get_auth_url(redirect_uri)

#this will block until we have the code
code = GetAuthCodeServer.get_auth_code(auth_url, redirect_uri)

client.auth_provider.authenticate(code, redirect_uri, client_secret)

Once your app is authenticated, you should have access to the OneDrive API, and can begin making calls using the SDK.

OneDrive for Business

To interact with the OneDrive API, your app must authenticate for a specific resource. Your app must first use the Resource Discovery helper to find out which service you can access. Then, you can build a client to access those resources. This uses a slightly different auth flow than the standard code flow - note the use of redeem_refresh_token with the service_resource_id of the service you want to access.

import onedrivesdk
from onedrivesdk.helpers import GetAuthCodeServer
from onedrivesdk.helpers.resource_discovery import ResourceDiscoveryRequest

redirect_uri = 'http://localhost:8080'
client_id = your_client_id
client_secret = your_client_secret
discovery_uri = 'https://api.office.com/discovery/'
auth_server_url='https://login.microsoftonline.com/common/oauth2/authorize'
auth_token_url='https://login.microsoftonline.com/common/oauth2/token'

http = onedrivesdk.HttpProvider()
auth = onedrivesdk.AuthProvider(http,
                                client_id,
                                auth_server_url=auth_server_url,
                                auth_token_url=auth_token_url)
auth_url = auth.get_auth_url(redirect_uri)
code = GetAuthCodeServer.get_auth_code(auth_url, redirect_uri)
auth.authenticate(code, redirect_uri, client_secret, resource=discovery_uri)
# If you have access to more than one service, you'll need to decide
# which ServiceInfo to use instead of just using the first one, as below.
service_info = ResourceDiscoveryRequest().get_service_info(auth.access_token)[0]
auth.redeem_refresh_token(service_info.service_resource_id)
client = onedrivesdk.OneDriveClient(service_info.service_resource_id + '/_api/v2.0/', auth, http)

Examples

Note: All examples assume that your app has already been Authenticated.

Upload an Item

returned_item = client.item(drive='me', id='root').children['newfile.txt'].upload('./path_to_file.txt')

Download an Item

root_folder = client.item(drive='me', id='root').children.get()
id_of_file = root_folder[0].id

client.item(drive='me', id=id_of_file).download('./path_to_download_to.txt')

Add a folder

f = onedrivesdk.Folder()
i = onedrivesdk.Item()
i.name = 'New Folder'
i.folder = f

returned_item = client.item(drive='me', id='root').children.add(i)

Copy an Item

from onedrivesdk.item_reference import ItemReference

ref = ItemReference()
ref.id = 'yourparent!id' #path also supported

copy_operation = client.item(drive='me', id='youritemtocopy!id').copy(name='new copied name', parent_reference=ref).post()

#copy_operation.item will return None until the copy has completed.
#If you would like to block until the operation has been completed
#and copy_operation.item is no longer None
copy_operation.poll_until_complete()

Rename an Item

renamed_item = onedrivesdk.Item()
renamed_item.name = 'NewItemName'
renamed_item.id = 'youritemtorename!id'

new_item = client.item(drive='me', id=renamed_item.id).update(renamed_item)

Paging through a collection

#get the top three elements of root, leaving the next page for more elements
collection = client.item(drive='me', id='root').children.request(top=3).get()

#get the first item in the collection
item = collection[0]

#get the next page of three elements, if none exist, returns None
collection2 = onedrivesdk.ChildrenCollectionRequest.get_next_page_request(collection, client).get()

Async operations

For async operations, you create an asyncio.coroutine which implements asyncio.ascompleted, and execute it with loop.run\_until\_complete.

import asyncio

@asyncio.coroutine
def run_gets(client):
    coroutines = [client.drive('me').request().get_async() for i in range(3)]
    for future in asyncio.as_completed(coroutines):
        drive = yield from future
        print(drive.id)

loop = asyncio.get_event_loop()
loop.run_until_complete(run_gets(client))   

Saving and Loading a Session

You can save your OAuth session details so that you don't have to go through the full OAuth flow every time you start your app. To do so, follow these steps:

auth_provider = onedrivesdk.AuthProvider(http_provider,
                                         client_id,
                                         scopes)
auth_provider.authenticate(code, redirect_uri, client_secret)

# Save the session for later
auth_provider.save_session()

#### Next time you start the app ####
auth_provider = onedrivesdk.AuthProvider(http_provider,
                                         client_id,
                                         scopes)
auth_provider.load_session()
auth_provider.refresh_token()
client = onedrivesdk.OneDriveClient(base_url, auth_provider, http_provider)

After the call to refresh_token() your AuthProvider will be ready to authenticate calls to the OneDrive API. This implementation is not complete, though.

  1. The default implementation of Session saves the session information in a Pickle file. Session data should be treated with equal protection as a password, so this is not safe for deployment to real users. You should re-implement Session to fit your app's needs.
  2. Calling .load_session() may throw an exception, depending on your implementation of Session. For example, the default implementation tries to open the file session.pickle, which may not exist and will raise FileNotFoundError. You will need to account for that here (or, even better, in your implementation of Session).

Using a Proxy

If you need to proxy your requests, you can use the helper class HttpProviderWithProxy.

import onedrivesdk
from onedrivesdk.helpers import http_provider_with_proxy

proxy = {
    'http': 'http://localhost:8888',
    'https': 'https://localhost:8888'
}
http = http_provider_with_proxy.HttpProviderWithProxy(proxy, verify_ssl=True)
auth = onedrivesdk.AuthProvider(http, my_client_id, ['onedrive.readwrite'])
client = onedrivesdk.OneDriveClient(my_base_url, auth, http)

All requests using that client will be proxied.

Code of Conduct

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

onedrive-sdk-python's People

Contributors

anadorr avatar cdmayer avatar colinnuk avatar d4n14l avatar hanhanwu avatar lokisharp avatar mimisasouvanh avatar rgregg avatar wiktorn avatar ybizeul 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  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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

onedrive-sdk-python's Issues

Error when expanding thumbnails in get Item request

Hi,
I'm getting an ImportError when I try to get a Item with expanded thumbnails field.
Here's the code to reproduce it:
returned_item = client.item(drive='me', id='file_id').request(expand="thumbnails").get()

I would like to obtain the Item and thumbnails information in a single request and this seems the right way to do it.
BTW I cloned the repo and patched the code adding the missing import statement and got the function to work, am I missing something?
I use python 2.7, onedrivesdk 1.1.4 .

Thank you

Accessing and Writing to Files In One Drive

Hi There,

I want to be able to read / write to files stored on 'one drive for business' which is due to be rolled out for our business.

However, the process seems a little complex to me. Microsoft site states that there is no SDK available for 'One drive for Business' is this correct.

Is any one here able to point me the right steps for achieving this?

crash when reading last_modified_date_time

Trying to access an item's item.last_modified_date_time on OneDrive for Business results in a crash:

(...)
  File ".../eggs/onedrivesdk-1.1.6-py2.7.egg/onedrivesdk/model/item.py", line 179, in last_modified_date_time
    return datetime.strptime(self._prop_dict["lastModifiedDateTime"].replace("Z", ""), "%Y-%m-%dT%H:%M:%S.%f")
  File "/usr/lib/python2.7/_strptime.py", line 325, in _strptime
    (data_string, format))
ValueError: time data '2016-10-20T11:31:57' does not match format '%Y-%m-%dT%H:%M:%S.%f'

Large file upload fails with 3 nested exceptions

This could be an issue with the client side network, but I would think the libraries retries chunks and give some informations in the output.

The upload starts and after a while, end up breaking with the following exceptions :

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/requests-2.11.1-py3.5.egg/requests/packages/urllib3/connectionpool.py", line 595, in urlopen
    chunked=chunked)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/requests-2.11.1-py3.5.egg/requests/packages/urllib3/connectionpool.py", line 363, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 1106, in request
    self._send_request(method, url, body, headers)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 1151, in _send_request
    self.endheaders(body)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 1102, in endheaders
    self._send_output(message_body)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 936, in _send_output
    self.send(message_body)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 905, in send
    self.sock.sendall(datablock)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 891, in sendall
    v = self.send(data[count:])
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 861, in send
    return self._sslobj.write(data)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 586, in write
    return self._sslobj.write(data)
BrokenPipeError: [Errno 32] Broken pipe

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/requests-2.11.1-py3.5.egg/requests/adapters.py", line 423, in send
    timeout=timeout
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/requests-2.11.1-py3.5.egg/requests/packages/urllib3/connectionpool.py", line 640, in urlopen
    _stacktrace=sys.exc_info()[2])
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/requests-2.11.1-py3.5.egg/requests/packages/urllib3/util/retry.py", line 261, in increment
    raise six.reraise(type(error), error, _stacktrace)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/requests-2.11.1-py3.5.egg/requests/packages/urllib3/packages/six.py", line 685, in reraise
    raise value.with_traceback(tb)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/requests-2.11.1-py3.5.egg/requests/packages/urllib3/connectionpool.py", line 595, in urlopen
    chunked=chunked)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/requests-2.11.1-py3.5.egg/requests/packages/urllib3/connectionpool.py", line 363, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 1106, in request
    self._send_request(method, url, body, headers)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 1151, in _send_request
    self.endheaders(body)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 1102, in endheaders
    self._send_output(message_body)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 936, in _send_output
    self.send(message_body)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/http/client.py", line 905, in send
    self.sock.sendall(datablock)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 891, in sendall
    v = self.send(data[count:])
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 861, in send
    return self._sslobj.write(data)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ssl.py", line 586, in write
    return self._sslobj.write(data)
requests.packages.urllib3.exceptions.ProtocolError: ('Connection aborted.', BrokenPipeError(32, 'Broken pipe'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "./onedrive.py", line 100, in <module>
    returned_item = client.item(drive='me', path=config['path']+"/"+upload).upload_async(upload)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/onedrivesdk-1.1.6-py3.5.egg/onedrivesdk/version_bridge/fragment_upload.py", line 173, in fragment_upload_async
    resp = upload_builder.post(i * __PART_SIZE, length)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/onedrivesdk-1.1.6-py3.5.egg/onedrivesdk/version_bridge/fragment_upload.py", line 121, in post
    return self.request(begin, length, options).post()
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/onedrivesdk-1.1.6-py3.5.egg/onedrivesdk/version_bridge/fragment_upload.py", line 57, in post
    entity = UploadSession(json.loads(self.send(data=self._file_handle).content))
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/onedrivesdk-1.1.6-py3.5.egg/onedrivesdk/request_base.py", line 151, in send
    data=data)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/onedrivesdk-1.1.6-py3.5.egg/onedrivesdk/http_provider.py", line 69, in send
    response = session.send(prepped)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/requests-2.11.1-py3.5.egg/requests/sessions.py", line 596, in send
    r = adapter.send(request, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/requests-2.11.1-py3.5.egg/requests/adapters.py", line 473, in send
    raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', BrokenPipeError(32, 'Broken pipe'))

unbound method load_session()

client.auth_provider.load_session()

Gives an error:

TypeError: unbound method load_session() must be called with Session instance as first argument (got nothing instead)

the auth_provider's load_session funtion :

    def load_session(self, **load_session_kwargs):

        self._session = self._session_type.load_session(**load_session_kwargs)

I don't know how to reslove it.
please help me .

Auth Business: cannot get anything at ResourceDiscoveryRequest().get_service_info

I am trying to add support to Business.

This is what I am trying to do:

import onedrivesdk
http = onedrivesdk.HttpProvider()
auth = onedrivesdk.AuthProvider(http,
                                client_id_business ,
                                auth_server_url=auth_server_url,
                                auth_token_url=auth_token_url)

auth_url = auth.get_auth_url(redirect_uri)

(Open the URL at the browse and get the code)

auth.authenticate(code, redirect_uri, client_secret, resource= 'https://api.office.com/discovery/')

Then

ResourceDiscoveryRequest().get_service_info(auth.access_token)

is returning empty list.

A manual trial with curl is showing:

curl -H "Authorization: Bearer {access_token_got_with_auth.access_token}" "https://api.office.com/discovery/v2.0/me/services" -k

{"@odata.context":"https://api.office.com/discovery/v2.0/me/$metadata#allServices","value":[]}

I am trying the graph API with the same access token, but received such error:

{
  "error": {
    "code": "InvalidAuthenticationToken",
    "message": "Access token validation failure.",
    "innerError": {
      "request-id": "82f68338-83ae-4659-9135-161ad1b399fd",
      "date": "2016-09-26T18:49:01"
    }
  }
}

And I cannot use graph SDK due to

>>> import msgraph
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/site-packages/msgraph/__init__.py", line 96, in <module>
    from .request.directory_object_request_builder import DirectoryObjectRequestBuilder
  File "/usr/local/lib/python2.7/site-packages/msgraph/request/directory_object_request_builder.py", line 11, in <module>
    from ..request.directory_object_check_member_groups import DirectoryObjectCheckMemberGroupsRequestBuilder
  File "/usr/local/lib/python2.7/site-packages/msgraph/request/directory_object_check_member_groups.py", line 12, in <module>
    from ..request import drive_item_collection 
  File "/usr/local/lib/python2.7/site-packages/msgraph/request/drive_item_collection.py", line 11, in <module>
    from ..request import drive_item_request_builder # import DriveItemRequestBuilder
  File "/usr/local/lib/python2.7/site-packages/msgraph/request/drive_item_request_builder.py", line 12, in <module>
    from ..request.drive_item_search import DriveItemSearchRequestBuilder
  File "/usr/local/lib/python2.7/site-packages/msgraph/request/drive_item_search.py", line 13, in <module>
    from ..request import drive_item_collection 
ImportError: cannot import name drive_item_collection

Where did I do wrong?

Many thanks.

Add support for recursive upload

Can you please add support for recursive upload (folder/subfolder1|subfolder2/file1|file2)?
I understand that this is more of a client implementation functionality, but I'm positively sure it is a demanded feature..

Getting permission denied when trying download function

Thanks so much for the python library. It is amazing!!!

This is probably just a user error from my side not knowing how to use the sdk correctly. I would like to use the delta function with the download function to sync the files from OneDrive to local folder. One way sync only to do some calculations and then upload one summary file back to onedrive.

I have started playing with the sdk and can run most of the functions except the download function.

As soon as I run:
client.item(id=collection_page[6].id).download('C:\Users\hannes.loots\Downloads')

on a file that I would like local I get
[Errno 13] Permission denied: 'C:\\Users\\hannes.loots\\Downloads'

I have given myslef permissions on everything I could:

client = onedrivesdk.get_default_client(client_id={My client ID},
                                        scopes=['wl.signin',
                                                'wl.offline_access',
                                                'onedrive.readwrite', 'onedrive.appfolder'])

Full error below

---------------------------------------------------------------------------
IOError                                   Traceback (most recent call last)
<ipython-input-13-7e48bcb91a8f> in <module>()
----> 1 client.item(id=collection_page[6].id).download('C:\Users\hannes.loots\Downloads')

C:\Users\hannes.loots\AppData\Local\Continuum\Anaconda2\lib\site-packages\onedrivesdk\request\item_request_builder.pyc in download(self, local_path)
    113                 downloaded to
    114         """
--> 115         return self.content.request().download(local_path)
    116 
    117 

C:\Users\hannes.loots\AppData\Local\Continuum\Anaconda2\lib\site-packages\onedrivesdk\request\item_content_request.pyc in download(self, content_local_path)
     67                 The path where the Item should be downloaded to
     68         """
---> 69         self.download_item(content_local_path)
     70 
     71 

C:\Users\hannes.loots\AppData\Local\Continuum\Anaconda2\lib\site-packages\onedrivesdk\request_base.pyc in download_item(self, path)
    186             self._headers,
    187             self.request_url,
--> 188             path)
    189 
    190         return response

C:\Users\hannes.loots\AppData\Local\Continuum\Anaconda2\lib\site-packages\onedrivesdk\http_provider.pyc in download(self, headers, url, path)
     91 
     92         if response.status_code == 200:
---> 93             with open(path, 'wb') as f:
     94                 for chunk in response.iter_content(chunk_size=1024):
     95                     if chunk:

IOError: [Errno 13] Permission denied: 'C:\\Users\\hannes.loots\\Downloads'

Refactor json encoding and decoding

JSON values are getting serialized and deserialized in-line. This makes it difficult to catch problems with invalid JSON (such as a response with an empty body, or with a body that is invalid JSON). Refactor the generated code to wrap the serialization/deserialization process and return proper OneDriveErrors when an invalid value is returned.

ConnectionResetError: [WinError 10054] upon uploading large file

I'm trying to upload a 800mb file, and I get the following error message:

c:\Python36\Scripts>python onedrive.py
https://login.live.com/oauth20_authorize.srf?response_type=code&scope=wl.signin+wl.offline_access+onedrive.readwrite&client_id=0000000044194611&redirect_uri=http%3A%2F%2Flocalhost%2F
127.0.0.1 - - [29/Jul/2016 00:59:10] "GET /?code=<my_code>
 HTTP/1.1" 200 -
<class 'str'>
Uploading item/s..
Traceback (most recent call last):
  File "c:\python36\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 578, in urlopen
    chunked=chunked)
  File "c:\python36\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 362, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "c:\python36\lib\http\client.py", line 1155, in request
    self._send_request(method, url, body, headers)
  File "c:\python36\lib\http\client.py", line 1200, in _send_request
    self.endheaders(body)
  File "c:\python36\lib\http\client.py", line 1151, in endheaders
    self._send_output(message_body)
  File "c:\python36\lib\http\client.py", line 985, in _send_output
    self.send(message_body)
  File "c:\python36\lib\http\client.py", line 954, in send
    self.sock.sendall(datablock)
  File "c:\python36\lib\ssl.py", line 887, in sendall
    v = self.send(data[count:])
  File "c:\python36\lib\ssl.py", line 857, in send
    return self._sslobj.write(data)
  File "c:\python36\lib\ssl.py", line 582, in write
    return self._sslobj.write(data)
ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "c:\python36\lib\site-packages\requests\adapters.py", line 403, in send
    timeout=timeout
  File "c:\python36\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 623, in urlopen
    _stacktrace=sys.exc_info()[2])
  File "c:\python36\lib\site-packages\requests\packages\urllib3\util\retry.py", line 255, in increment
    raise six.reraise(type(error), error, _stacktrace)
  File "c:\python36\lib\site-packages\requests\packages\urllib3\packages\six.py", line 309, in reraise
    raise value.with_traceback(tb)
  File "c:\python36\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 578, in urlopen
    chunked=chunked)
  File "c:\python36\lib\site-packages\requests\packages\urllib3\connectionpool.py", line 362, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "c:\python36\lib\http\client.py", line 1155, in request
    self._send_request(method, url, body, headers)
  File "c:\python36\lib\http\client.py", line 1200, in _send_request
    self.endheaders(body)
  File "c:\python36\lib\http\client.py", line 1151, in endheaders
    self._send_output(message_body)
  File "c:\python36\lib\http\client.py", line 985, in _send_output
    self.send(message_body)
  File "c:\python36\lib\http\client.py", line 954, in send
    self.sock.sendall(datablock)
  File "c:\python36\lib\ssl.py", line 887, in sendall
    v = self.send(data[count:])
  File "c:\python36\lib\ssl.py", line 857, in send
    return self._sslobj.write(data)
  File "c:\python36\lib\ssl.py", line 582, in write
    return self._sslobj.write(data)
requests.packages.urllib3.exceptions.ProtocolError: ('Connection aborted.', ConnectionResetError(10054, 'An existing connection was forcibly closed by the remote host', None, 10054, None))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "onedrive.py", line 23, in <module>
    client.item(drive="me", id="8930240577EB1134%2166557").children["Agron_reshumon.rar"].upload("//dd-wrt/usb/Upload/Agron_reshumon.rar")
  File "c:\python36\lib\site-packages\onedrivesdk\request\item_request_builder.py", line 134, in upload
    return self.content.request().upload(local_path)
  File "c:\python36\lib\site-packages\onedrivesdk\request\item_content_request.py", line 59, in upload
    entity_response = self.send(path=content_local_path)
  File "c:\python36\lib\site-packages\onedrivesdk\request_base.py", line 145, in send
    path=path)
  File "c:\python36\lib\site-packages\onedrivesdk\http_provider.py", line 61, in send
    response = session.send(prepped)
  File "c:\python36\lib\site-packages\requests\sessions.py", line 585, in send
    r = adapter.send(request, **kwargs)
  File "c:\python36\lib\site-packages\requests\adapters.py", line 453, in send
    raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionResetError(10054, 'An existing connection was forcibly closed by the remote host', None, 10054, None))

I guess this error is probably due to a limit of the uploaded file size (100mb)?
If so, it would be nice if the SDK checks the file size prior to uploading, and breaks it to chunks, or notifies, or this feature is already implemented?

ValueError when uploading large file

When I try to upload large files (500MB - 2000MB) I often get the following exception:

Traceback (most recent call last):
File "OneDriveUpload.py", line 56, in UploadFile
client.item(drive="me", path=remoteFilePath).upload_async(localFilePath)
File "/usr/local/lib/python3.4/dist-packages/onedrivesdk/version_bridge/fragment_upload.py", line 170, in fragment_upload_async
resp = upload_builder.post(i * PART_SIZE, length)
File "/usr/local/lib/python3.4/dist-packages/onedrivesdk/version_bridge/fragment_upload.py", line 118, in post
return self.request(begin, length, options).post()
File "/usr/local/lib/python3.4/dist-packages/onedrivesdk/version_bridge/fragment_upload.py", line 56, in post
entity = UploadSession(json.loads(self.send(data=self._file_handle).content))
File "/usr/local/lib/python3.4/dist-packages/onedrivesdk/request_base.py", line 151, in send
data=data)
File "/usr/local/lib/python3.4/dist-packages/onedrivesdk/http_provider.py", line 71, in send
custom_response = HttpResponse(response.status_code, response.headers, response.text)
File "/usr/local/lib/python3.4/dist-packages/onedrivesdk/http_response.py", line 46, in __init

message = json.loads(self.content)
File "/usr/lib/python3.4/json/init.py", line 318, in loads
return _default_decoder.decode(s)
File "/usr/lib/python3.4/json/decoder.py", line 343, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib/python3.4/json/decoder.py", line 361, in raw_decode
raise ValueError(errmsg("Expecting value", s, err.value)) from None
ValueError: Expecting value: line 1 column 1 (char 0)

Anyone else having this issue?

Using python 3.4 and latest sdk (1.1.2)

Uploading an item doesn't work when referring to an item by ID

I'm trying to upload big file into and running into the issue where I have to use async methods for this.

I came across #42 but couldn't find a solution to my problem.

Are async operation only compatible with Python 3?

I'm trying to use a stock python from macOS Sierra, and here is what I'm running into :

Traceback (most recent call last):
  File "./onedrive.py", line 114, in <module>
    returned_item = client.item(drive='me', id=config['item_id']).children[os.path.basename(upload)].upload_async(upload)
AttributeError: 'ItemRequestBuilder' object has no attribute 'upload_async'
ERROR: Build failed: exit status 1
FATAL: exit status 1                               

If I run with python 3.5, small files works, but big files :

Traceback (most recent call last):
  File "./onedrive.py", line 114, in <module>
    returned_item = client.item(drive='me', id=config['item_id']).children[os.path.basename(upload)].upload_async(upload)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/onedrivesdk-1.1.6-py3.5.egg/onedrivesdk/version_bridge/fragment_upload.py", line 160, in fragment_upload_async
    session = self.create_session(item).post()
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/onedrivesdk-1.1.6-py3.5.egg/onedrivesdk/request/item_create_session.py", line 93, in post
    return self.request().post()
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/onedrivesdk-1.1.6-py3.5.egg/onedrivesdk/request/item_create_session.py", line 59, in post
    entity = UploadSession(json.loads(self.send(self.body_options).content))
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/onedrivesdk-1.1.6-py3.5.egg/onedrivesdk/request_base.py", line 163, in send
    content=content_dict)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/onedrivesdk-1.1.6-py3.5.egg/onedrivesdk/http_provider.py", line 71, in send
    custom_response = HttpResponse(response.status_code, response.headers, response.text)
  File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/onedrivesdk-1.1.6-py3.5.egg/onedrivesdk/http_response.py", line 59, in __init__
    raise OneDriveError(message["error"], self.status)
onedrivesdk.error.OneDriveError: invalidRequest - API not found

What is the requirement to run big files upload?

Request: Upload function using data instead of path

Hey Microsoft,

I am looking into uploading entire zip-files from local folders created just in time. I can obviously write a temporary file, upload it and then delete it again. However, this is associated with some IO lag and puts some stress on the drive. Something which I would like to avoid when executing my python script on a portable flash drive or a rather slow HDD (possibly further slowed down by antivirus software). Hence, I had the idea to use an in memory zip file (see http://stackoverflow.com/questions/2463770/python-in-memory-zip-library ).

However, this possibility is obstructed by the the upload function of the SDK, which - to the best of my knowledge - only supports path but not data. Unfortunately, I lack the skill to effectively and generically extend the SDK myself.

Thus my request to introduce the possibility to use data instead of path for the upload function. What do you think?

Regards,
Stulle

SharePoint upload

Is it possible to upload a file to the Shared Documents library of a SharePoint site with this SDK?
I'm able to authenticate with Azure AD and upload to a OneDrive for Business folder, but keep getting this error:
{'error_description': "Exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' was thrown."}
when trying to upload to a SharePoint folder.

The code I'm using:

(authentication)
client = onedrivesdk.OneDriveClient('https://{tenant}.sharepoint.com/{site}/_api/v2.0/', auth, http)
client.item(path='/drive/special/documents').children['test.xlsx'].upload('test.xlsx')

OneDrive for Business / list exception KeyError: 'value'

following the instructions in issue #16 i'm attempting to connect to onedrive for business and list the items in the root, but get an exception when attempting the list. is there something i'm doing incorrectly?

import onedrivesdk

client_id = '17a...'
client_secret = 'RKa...'
redirect_uri = 'https://localhost:...'
onedrive_base_url = 'https://...-my.sharepoint.com/_api/v2.0'

auth_scopes = [ 'wl.signin', 'wl.offline_access', 'onedrive.readwrite' ]


# using this technique b/c i'll need a custom Session class once this is working
http_provider = onedrivesdk.http_provider.HttpProvider()
auth_provider = onedrivesdk.auth_provider.AuthProvider(http_provider=http_provider,
                                                       client_id=client_id,
                                                       scopes=auth_scopes)
client = onedrivesdk.OneDriveClient(onedrive_base_url, auth_provider, http_provider)

# code obtained from logging in on browser
code = "M66..."
client.auth_provider.authenticate(code, redirect_uri, client_secret)

client.item(drive="me", id="root").children.get()

# this last call raises:
#
#Traceback (most recent call last):
#  File "onedrive_test.py", line 54, in <module>
#    client.item(drive="me", id="root").children.get()
#  File "/Library/Python/2.7/site-packages/onedrivesdk/request/children_collection.py", line 131, in get
#    return self.request().get()
#  File "/Library/Python/2.7/site-packages/onedrivesdk/request/children_collection.py", line 72, in get
#    return self._page_from_response(collection_response)
#  File "/Library/Python/2.7/site-packages/onedrivesdk/collection_base.py", line 51, in _page_from_response
#    return response.collection_page
#  File "/Library/Python/2.7/site-packages/onedrivesdk/request/children_collection.py", line 148, in collection_page
#    self._collection_page = ChildrenCollectionPage(self._prop_dict["value"])
#KeyError: u'value'

Need more detailed error on unexpected redirect_uri

When executing the authentication sample code in /README.md, the following error is thrown when a redirect_uri is specified which doesn't contain a port:

Traceback (most recent call last): File "C:\<FilePath>\Script.py", line 15, in <module> code = GetAuthCodeServer.get_auth_code(auth_url, redirect_uri) File "C:\Program Files (x86)\Python35-32\lib\site-packages\onedrivesdk\helpers\GetAuthCodeServer.py", line 51, in get_auth_code HOST, PORT = urlparse(redirect_uri).netloc.split(':') ValueError: not enough values to unpack (expected 2, got 1) Press any key to continue . . .

For developers unfamiliar with OAuth in Python the reason for this isn't intuitive to derive. A check should be made early on to ensure the redirect_uri is valid for the scenario, and an exception should be raised to clearly indicate that.

Exception on paging through selection

I am still working on my backup script (see #21 ). As one would expect, I am recursively looping through the various directories in the directory structure (rather deep structures, up to approx. 10 levels with between 1 and a couple of hundred files per directory). Now, I ran into an issue where I am trying to get a collection page and the json decoder throws an exception. Some more trial and error eventually got me to realize that the supposed json-string for decoding is actually empty. Here is the call stack followed by the line which throws the error (please ignore my crude style of coding).

Traceback (most recent call last):

  File "<ipython-input-14-f4000242bd12>", line 1, in <module>
    debugfile('F:/IWU/Python_new/OneDriveUpdate.py', wdir='F:/IWU/Python_new')

  File "F:\Software\WinPython\python-3.4.3.amd64\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 808, in debugfile
    debugger.run("runfile(%r, args=%r, wdir=%r)" % (filename, args, wdir))

  File "F:\Software\WinPython\python-3.4.3.amd64\lib\bdb.py", line 431, in run
    exec(cmd, globals, locals)

  File "<string>", line 1, in <module>

  File "F:\Software\WinPython\python-3.4.3.amd64\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 786, in runfile
    execfile(filename, namespace)

  File "F:\Software\WinPython\python-3.4.3.amd64\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 87, in execfile
    exec(compile(open(filename, 'rb').read(), filename, 'exec'), namespace)

  File "f:/iwu/python_new/onedriveupdate.py", line 553, in <module>
    if not checkDirContent(rootDir, upDirID, posFilter):

  File "f:/iwu/python_new/onedriveupdate.py", line 278, in checkDirContent
    if not checkDirContent(localItem['path'], dirID, None, (localItem['name'] == 'Zotero'), (defaultDelete and localItem['name'] == 'storage')):

  File "f:/iwu/python_new/onedriveupdate.py", line 278, in checkDirContent
    if not checkDirContent(localItem['path'], dirID, None, (localItem['name'] == 'Zotero'), (defaultDelete and localItem['name'] == 'storage')):

  File "f:/iwu/python_new/onedriveupdate.py", line 241, in checkDirContent
    upParentItemsList = getParentItemsList(upParentDirID,dirPath)

  File "f:/iwu/python_new/onedriveupdate.py", line 100, in getParentItemsList
    upParentItemsList.append(client.item(id=str(upParentDirID)).children.request().get())

  File "F:\Software\WinPython\python-3.4.3.amd64\lib\site-packages\onedrivesdk\request\children_collection.py", line 90, in get
    collection_response = ChildrenCollectionResponse(json.loads(self.send().content))

  File "F:\Software\WinPython\python-3.4.3.amd64\lib\json\__init__.py", line 318, in loads
    return _default_decoder.decode(s)

  File "F:\Software\WinPython\python-3.4.3.amd64\lib\json\decoder.py", line 343, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())

  File "F:\Software\WinPython\python-3.4.3.amd64\lib\json\decoder.py", line 361, in raw_decode
    raise ValueError(errmsg("Expecting value", s, err.value)) from None

ValueError: Expecting value: line 1 column 1 (char 0)

The code (the essential bit; note I am creating a list of pages to retrieve all items, not just 200, for later use) --> second row causes exception:

        upItemsList = []
        upItemsList.append(client.item(id=str(upParentDirID)).children.request().get())
        while len(upParentItemsList[i]) == 200 and len(upParentItemsList[i]) != 0:
            # Loop while the count is 200 (last one will have less)
            upParentItemsList.append(upParentItemsList[i].next_page_request.get())
            i += 1

Eventual function which crashes is:

    def raw_decode(self, s, idx=0):
        """Decode a JSON document from ``s`` (a ``str`` beginning with
        a JSON document) and return a 2-tuple of the Python
        representation and the index in ``s`` where the document ended.

        This can be used to decode a JSON document from a string that may
        have extraneous data at the end.

        """
        try:
            obj, end = self.scan_once(s, idx)
        except StopIteration as err:
            raise ValueError(errmsg("Expecting value", s, err.value)) from None
        return obj, end

I hope this helps - and it's not really my fault to begin with.

The Borg: All instantiated objects carry the same state

>>> from onedrivesdk import *
>>> i = Item()
>>> i.name = 'a name'
>>> i2 = Item()
>>> i2.name
'a name'
>>> i2.name = 'hi there'
>>> i.name
'hi there'

All instances share the exact same attributes. The reason for that is this constructor, which is recurring among all models

class Item(OneDriveObjectBase):

    def __init__(self, prop_dict={}):
        self._prop_dict = prop_dict

The default parameter {} is evaluated once when the function definition is executed, resulting in all instances sharing the same single _prop_dict dictionary object (explained at https://docs.python.org/3/reference/compound_stmts.html#function-definitions). Combined with the fact that all attributes accesses are done through property setters/getters that modify this dictionary, we end up with a re-imagining of the Borg pattern

adding folder fails

I try to add a folder "foo" into the (existing) folder "/a/b/" with the following code:

    i = onedrivesdk.Item()
    i.name = "foo"
    i.folder = onedrivesdk.Folder()
    cs = client.item(path="/a/b/").children
    cs.add(i)

Yet I just get:

File "C:\Users\info\AppData\Local\Programs\Python\Python35-32\lib\site-packages\onedrivesdk\request\children_collection.py", line 43, in add
    entity = Item(json.loads(self.send(entity).content))
NameError: name 'Item' is not defined

Exception on last_modified_date_time

Hi,

I have been using a backup script which used the live_api used in an older version of onedrive-d. Using this script, I uploaded all the files in a specific folder.

I am in the process of updating this script of mine to work use onedrivesdk. However, I noticed that the sdk has some issues when I try to check the last_modified_date_time of the files I have already uploaded. The traceback looks as follows:

Traceback (most recent call last):

  File "<ipython-input-24-f4000242bd12>", line 1, in <module>
    debugfile('F:/IWU/Python_new/OneDriveUpdate.py', wdir='F:/IWU/Python_new')

  File "F:\Software\WinPython\python-3.4.3.amd64\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 808, in debugfile
    debugger.run("runfile(%r, args=%r, wdir=%r)" % (filename, args, wdir))

  File "F:\Software\WinPython\python-3.4.3.amd64\lib\bdb.py", line 431, in run
    exec(cmd, globals, locals)

  File "<string>", line 1, in <module>

  File "F:\Software\WinPython\python-3.4.3.amd64\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 786, in runfile
    execfile(filename, namespace)

  File "F:\Software\WinPython\python-3.4.3.amd64\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 87, in execfile
    exec(compile(open(filename, 'rb').read(), filename, 'exec'), namespace)

  File "f:/iwu/python_new/onedriveupdate.py", line 532, in <module>
    if not checkDirContent(rootDir, upDirID, posFilter):

  File "f:/iwu/python_new/onedriveupdate.py", line 262, in checkDirContent
    if not checkDirContent(localItem['path'], dirID, None, (localItem['name'] == 'Zotero'), (defaultDelete and localItem['name'] == 'storage')):

  File "f:/iwu/python_new/onedriveupdate.py", line 262, in checkDirContent
    if not checkDirContent(localItem['path'], dirID, None, (localItem['name'] == 'Zotero'), (defaultDelete and localItem['name'] == 'storage')):

  File "f:/iwu/python_new/onedriveupdate.py", line 262, in checkDirContent
    if not checkDirContent(localItem['path'], dirID, None, (localItem['name'] == 'Zotero'), (defaultDelete and localItem['name'] == 'storage')):

  File "f:/iwu/python_new/onedriveupdate.py", line 284, in checkDirContent
    ulFileTimeDT = file.last_modified_date_time

  File "F:\Software\WinPython\python-3.4.3.amd64\lib\site-packages\onedrivesdk\model\item.py", line 196, in last_modified_date_time
    return datetime.strptime(self._prop_dict["lastModifiedDateTime"].replace("Z", ""), "%Y-%m-%dT%H:%M:%S.%f")

  File "F:\Software\WinPython\python-3.4.3.amd64\lib\_strptime.py", line 500, in _strptime_datetime
    tt, fraction = _strptime(data_string, format)

  File "F:\Software\WinPython\python-3.4.3.amd64\lib\_strptime.py", line 337, in _strptime
    (data_string, format))

ValueError: time data '2014-11-05T11:47:34' does not match format '%Y-%m-%dT%H:%M:%S.%f'

Note the missing microseconds. For the time being I am simply using a try/except to default to the 1970/1/1. Anyhow, I do not know what causes the time to be weird/not like expected. I assume this is either an issue on the server side (bad truncation if microseconds==0?) or an issue in the sdk which should be caught on your end. It would be awesome if you could attend to the matter.

Regards,
Stulle

Authentication on non-GUI system (no web browser)

I saw issue #8 regarding a workaround for authentication that requires running a script on another system first.

I, too, am experiencing the same problem. I have a Linux system with no GUI -- only links / w3m installed, and Microsoft login is failing because my browser doesn't support Javascript.

Would doing something similar to what Google's python API / oauth2client (https://github.com/google/oauth2client) does be possible?

(Applicable code here: https://github.com/google/oauth2client/blob/master/oauth2client/tools.py)

I use their python client and the authentication process is very simple when you don't have a local browser.

When you run your script the first time, you pass a "--noauth_local_webserver" parameter on the command line which causes their client to genereate a URL that you then go to on another system that does have a web browser. The script then blocks waiting on you to login. Once you login on your other system, the script saves off the credentials and moves on.

All subsequent times that you run your script, you don't have to specify the extra command line option. The credentials are loaded and used, and your script works just fine.

This type of flow is very simple on the end user and doesn't require having additional special setup (other than access to some device -- even a smart phone -- with a web browser).

Allow using the client without the authorization flow of the SDK

I use my own OAuth client for authorization with the implicit flow and I successfully retrieved the access token etc. from OneDrive.
The SDK however doesn't allow me to create an authenticated OneDriveClient object with my already obtained access token. Is there any way around this? I really want to avoid the work needed for implementing my own client based on the REST API.

Upload sockets left open with FIN_WAIT

Looking at sockets used by the big file upload I noticed sockets left open in FinWait2 state.

Every single socket used to upload the 10m pieces. After some research, I saw this documentation :

https://kb.iu.edu/d/ajmi

Is it possible onedrive-sdk-python code doesn't cleanly close the socket?

[...]
   tcp4 10.0.1.136:58718<->a-0011.a-msedge.net:443                                          en0      FinWait2        6026 B            10 MiB     0 B       0 B
   tcp4 10.0.1.136:58727<->a-0011.a-msedge.net:443                                          en0      FinWait2        6026 B            10 MiB     0 B       0 B
   tcp4 10.0.1.136:58739<->a-0011.a-msedge.net:443                                          en0      FinWait2        6026 B            10 MiB     0 B       0 B

authentication on raspberry pi

I want to use the new onedrive-sdk with my raspberry pi running raspbian, but i have problems to acquire the authentication code.
As we can see in the source code the authenticater uses the webbrowser.open command to get the authentication code, so i tried to install Lynx to get this command working,
But each time my program calls GetAuthCodeServer.get_auth_code(auth_url, redirect_uri), the following error is printed to the console:
Error opening terminal: emacs Error opening terminal: emacs.

Is it even possible to authenticate without a graphical browser?

Best Regards,
Thomas

Authentication Problem

HI
I am trying to build a onedrive ubuntu app using python sdk, but the authentication process is giving me some problems.
I am trying to run the example CommandLineFileExplorer.py script with my own client_id and client_secret.

I registered my app and used the application_id for 'client_id' and password for 'client_secret'. When I try to get the code by authentication, I only get a message saying 'Microsoft is unable to complete this request'.

Any help regarding this is appreciated.

Thanks

Malformed auth_url returned

Here is a sample of an URL returned by auth.get_auth_url (as in the sample code) :

u"('https://login.microsoftonline.com/common/oauth2/authorize',)?redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&response_type=code&client_id=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

Because of that, the auth window doesn't open

Onedrive web interface is not updating

Not sure where the right place to post this is, but since I'm using Python, I'm posting here. After I upload files, in the case where there is a new version of the file with same name (using the default overwrite behavior)... the web interfaces does not update the file contents, even though the file update times shows as changed. I have tried with new sessions in multiple browsers, and nothing has changed, so this is definitely a server-side issue... I am assuming that they are doing some type of server-side caching of file object contents... I originally thought that this was a problem in my code, but then I looked at the same file with the Outlook App on iOS and the new file content was displayed...

CLI tool

Do you plan to provide a CLI tool that implement all/most SDK features?

Authentication without needing a web browser

I'm running onedrive-sdk for python on an embedded device, and I get the following error message:

root@DD-WRT:/opt/bin# python3.5 onedrivesdk3.5.py
Traceback (most recent call last):
  File "onedrivesdk3.5.py", line 16, in <module>
    code = GetAuthCodeServer.get_auth_code(auth_url, redirect_uri)
  File "/opt/lib/python3.5/site-packages/onedrivesdk/helpers/GetAuthCodeServer.py", line 60, in get_auth_code
    s = GetAuthCodeServer((host_address, port), code_acquired, GetAuthCodeRequestHandler)
  File "/opt/lib/python3.5/site-packages/onedrivesdk/helpers/GetAuthCodeServer.py", line 76, in __init__
    HTTPServer.__init__(self, server_address, RequestHandlerClass)
  File "/opt/lib/python3.5/socketserver.py", line 443, in __init__
    self.server_bind()
  File "/opt/lib/python3.5/http/server.py", line 138, in server_bind
    socketserver.TCPServer.server_bind(self)
  File "/opt/lib/python3.5/socketserver.py", line 457, in server_bind
    self.socket.bind(self.server_address)
OSError: [Errno 98] Address already in use

That is after I've manually added 'webbrowser.py' to lib dir, otherwise I get a module not found exception.

If I get the code from a PC, by running the auth process provided in an example, I get the following error:

root@DD-WRT:/opt/bin# python3.5 onedrivesdk3.5.py
Traceback (most recent call last):
  File "onedrivesdk3.5.py", line 20, in <module>
    client.auth_provider.authenticate(code, redirect_uri, client_secret)
  File "/opt/lib/python3.5/site-packages/onedrivesdk/auth_provider.py", line 169, in authenticate
    data=params)
  File "/opt/lib/python3.5/site-packages/onedrivesdk/http_provider.py", line 71, in send
    custom_response = HttpResponse(response.status_code, response.headers, response.text)
  File "/opt/lib/python3.5/site-packages/onedrivesdk/http_response.py", line 51, in __init__
    raise Exception(str(message["error"]))
Exception: invalid_grant

Please add support for manual auth (done on a PC) , like in python-onedrive project.

Changelog?

I can't seem to locate the project's changelog

url quote in children collection url build

Hello,

I use the following code to upload a file which filename is "a + b.txt".
But the uploaded file's name was changed to "a b.txt".

client.item(drive='me', id='root').children['a + b.txt'].upload('./path_to_file.txt')

I trace the source code, found the url build method does not quote the filename.

class RequestBuilderBase(object):  
  def append_to_request_url(self, url_ssegment):  
     return self._request_url + "/" + url_segment  

so i changed my code to:
client.item(drive='me', id='root').children[urllib.quote('a + b.txt')].upload('./path_to_file.txt')

then the uploaded file's name is correct.

Is this a bug?
Or I should quote the file name for the children[] collection?

Kind regards
Frank

Does not allow to authenticate business accounts

By using the authentication example, I'm able to authenticate/authorize the client using personal account credentials, but, using business credentials, I get from the auth page a message saying that the account doesn't exist, therefore I cant authorize the client.

The use case that I need to implement is for business accounts

Add support for query parameters (expand, filter, sort, etc.)

I was wondering how i could use the parameters listed here, when requesting child items.
I can`t seem to get the syntax right, when trying to get the results sorted by "lastmodifieddateTime".
Example source code would be appreciated.

collection = client.item(drive="me", id="5A49630B8FC52EAA!109").children.request( >> ? <<).get()

Broken pipe

Hello,

I am getting

requests.packages.urllib3.exceptions.ProtocolError: ('Connection aborted.', error(32, 'Broken pipe'))

early on when trying to upload a large file (>4GB).
I have successfully uploaded small files using the example provided
returned_item = client.item(drive='me', id='root').children['newfile.txt'].upload('./path_to_file.txt')
(so app declared, went through the initial drill etc etc), but fails for larger ones.

Please advise.

Kind regards
Paul

Clearer errors when a field is required

session = client.item(drive="me", path="backup/test_file").create_session().post()

Gives a boneheaded stack trace:

Traceback (most recent call last):
  File "create-session.py", line 34, in <module>
    session = client.item(drive="me", path="backupy/test_file").create_session().post()
  File "/home/w/python/onedrive/venv/lib/python3.4/site-packages/onedrivesdk-1.0.1-py3.4.egg/onedrivesdk/request/item_request_builder.py", line 229, in create_session
    return ItemCreateSessionRequestBuilder(self.append_to_request_url("upload.createSession"), self._client, item=item)
  File "/home/w/python/onedrive/venv/lib/python3.4/site-packages/onedrivesdk-1.0.1-py3.4.egg/onedrivesdk/request/item_create_session.py", line 84, in __init__
    self._method_options["item"] = item._prop_dict
AttributeError: 'NoneType' object has no attribute '_prop_dict'

It's because create_session() actually requires an Item. This probably shows up in other places too. Make sure that is clear by throwing an error when an Item is not provided.

Size field mismatch size of content downloaded

I noticed that for some (not all) files in my OneDrive Personal account the size reported by the API is not consistent with the length of content actually downloaded, yet the SHA-1 hash values match.

For example, I have a JPEG file named IMG_0100.JPG whose size is 62671 bytes reported by API yet the downloaded file is only 57814 bytes. However, the API says the SHA-1 hash is D4AE13DB398E5F51A1DCA6908212B2EF855AB04C which matches the SHA-1 hash of the downloaded file. Because the hashes match, I think the file is downloaded properly and thus the file size reported by the OS is correct.

Follow-ups:

  • I re-uploaded the downloaded file back to OneDrive yet value of size field of the returned Item does not change.
  • Most such files seem MSOffice, PDF, or image files. But I don't have various types of files in my OneDrive.

Any idea why this happened?

I'm running Ubuntu 16.04 64-bit and using Python 3.5.

Cross-reference: OneDrive/onedrive-api-docs#492

File size corruption issue on uploaded files

[ NB I've put the files from this report in a gist which you may find easier to use.]

To reproduce, run the python program onedrive_bug.py. This needs the python onedrivesdk. This uploades the file goof.png repeatedly, to the root of your onedrive as 1.png, 2.png, etc.

If you run it after a while you'll see a size mis-match.

This means that the 97k file is apparently 200k. If you look in the web interface it also appears as 200k, however if you download it is really only 97k.

I don't think this is a bug in the python library, rather a bug in Onedrive.

I think the bug depends on the particular file being uploaded.

A user of my program rclone ( @Darkvater ) noticed the file corruptions originally in rclone/rclone#399 and supplied the png file which is used for the demo here.

This means that this bug has been reproduced with the Python SDK and my own Go SDK and from at least 4 different environments (computers, OS, net connections etc).

This log is from running onedrive_bug.py on Linux Ubuntu Wily 15.10 with python 2.7.10 and the onedrive sdk master installed in a virtualenv.

$ python onedrive_bug.py 
Created new window in existing browser session.
127.0.0.1 - - [25/Mar/2016 16:38:50] "GET /?code=xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx HTTP/1.1" 200 -
Uploaded test file: 0.png, size 97258
Uploaded test file: 1.png, size 97258
Uploaded test file: 2.png, size 97258
Uploaded test file: 3.png, size 97258
Uploaded test file: 4.png, size 97258
Uploaded test file: 5.png, size 97258
Uploaded test file: 6.png, size 205029
**** Size mismatch
Uploaded test file: 7.png, size 205029
Uploaded test file: 8.png, size 205029
Uploaded test file: 9.png, size 205029
Uploaded test file: 10.png, size 97258
**** Size mismatch
Uploaded test file: 11.png, size 97258
Uploaded test file: 12.png, size 97258
Uploaded test file: 13.png, size 97258

Here is onedrive_bug.py

#!/usr/bin/env python
"""
This demonstrates a bug in onedrive
"""

import os
import onedrivesdk
from onedrivesdk.helpers import GetAuthCodeServer
import SocketServer
from datetime import datetime

SocketServer.TCPServer.allow_reuse_address = True # monkey patch so as to set SO_REUSEADDR
GetAuthCodeServer.allow_reuse_address = True

TEST_FILE="goof.png"

def main():
    redirect_uri = "http://localhost:8080/"
    client_secret = "BqaTYqI0XI7wDKcnJ5i3MvLwGcVsaMVM"

    client = onedrivesdk.get_default_client(client_id='00000000481695BB',
                                            scopes=['wl.signin',
                                                    'wl.offline_access',
                                                    'onedrive.readwrite'])
    auth_url = client.auth_provider.get_auth_url(redirect_uri)

    # Block thread until we have the code
    code = GetAuthCodeServer.get_auth_code(auth_url, redirect_uri)
    # Finally, authenticate!
    client.auth_provider.authenticate(code, redirect_uri, client_secret)

    root = client.item(drive="me", id="root")
    last_uploaded_size = None
    for i in range(100):
        name = "%d.png" % i
        uploaded_file = root.children[name].upload(TEST_FILE)
        print "Uploaded test file: %s, size %d" % (name, uploaded_file.size)
        if last_uploaded_size != None:
            if last_uploaded_size != uploaded_file.size:
                print "**** Size mismatch"
        last_uploaded_size = uploaded_file.size

if __name__ == "__main__":
    main()

And here is goof.png
goof

Add a folder example is broken

Trying the example found in the README:

f = onedrivesdk.Folder()
i = onedrivesdk.Item()
i.name = 'New Folder'
i.folder = f

returned_item = client.item(drive='me', id='root').children.add(i)

Throws an error:

AttributeError: 'ChildrenCollectionRequestBuilder' object has no attribute 'add'

Resume upload

How resume upload's? (large file)

please an example

Setter and getter on datetime properties are inconsistent

I have some code where I am trying to modify the last_modified_time on item.file_system_info so I can preserve the timestamp of the original data I'm uploading.

The problem can be demonstrated without even uploading the file:

I'm using the following code to create the Item I was going to use to patch the uploaded file with:
fsi = onedrivesdk.FileSystemInfo()
fsi.last_modified_date_time = dt # dt is initialized by datetime.fromtimestamp()
fsi.created_date_time = dt
i = onedrivesdk.Item()
i.id = item.id
i.file_system_info = fsi

Immediately doing the following results in an error:

print fsi.last_modified_date_time

.
.
.
File "/home/clarkl/.local/lib/python2.7/site-packages/onedrivesdk/model/file_system_info.py", line 62, in last_modified_date_time
return datetime.strptime(self._prop_dict["lastModifiedDateTime"].replace("Z", ""), "%Y-%m-%dT%H:%M:%S.%f")
File "/usr/lib/python2.7/_strptime.py", line 332, in _strptime
(data_string, format))
ValueError: time data '2013-10-11T15:31:03' does not match format '%Y-%m-%dT%H:%M:%S.%f'

The problem is that the setter function for the dates in file_system_info use .isoformat() which, if microseconds is 0, does not include that component in the time string (i.e. no .000000). But, the getter function expects it to be there with the ".%f" in the format string.

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.