python-o365 icon indicating copy to clipboard operation
python-o365 copied to clipboard

"Protocol not provided to Api Component" when copying files from a shared OneDrive

Open jkunczik opened this issue 1 year ago • 3 comments

I have a problem copying files in a shared OneDrive.

Error Description

When attempting to copy files from one directory to another in a shared OneDrive using the following Python code:

operation = item.copy(target=dest_folder, name=new_name)

The following error is encountered:

  File "...\miniconda3\envs\Automations\Lib\site-packages\O365\drive.py", line 153, in __init__
    super().__init__(
  File "...\miniconda3\envs\Automations\Lib\site-packages\O365\utils\utils.py", line 344, in __init__
    raise ValueError('Protocol not provided to Api Component')

It is worth noting that despite the error, the copy operation still succeeds.

Steps to Reproduce

  1. Attempt to copy a DriveItem from a shared OneDrive using the provided code snippet.

Origin of the Error

Upon inspecting the source code, it was discovered that the protocol is set within the CopyOperation class:

class CopyOperation(ApiComponent):
    ...
    def __init__(self, *, parent=None, con=None, **kwargs):
    ...
    super().__init__(
            protocol=parent.protocol if parent else kwargs.get('protocol'),
            main_resource=main_resource)
    ...

This is invoked from the DriveItem.copy() method with the arguments CopyOperation(parent=self.drive, ...). Further investigation revealed that self.drive is set to None.

Workaround

A temporary workaround for this issue is to wrap the copy statement in a try/except block.

Question

Is there a more elegant solution to address this problem?

jkunczik avatar Jan 25 '24 13:01 jkunczik

This makes no sense.

In order for CopyOperation to work, it needs a connection object. The connections objects comes directly from the parent attribute (or con if provided but it's not provided from driveitem.copy):

https://github.com/O365/python-o365/blob/417d8cf2e7fa9cea19be0baed197c5f3a9e55a9d/O365/drive.py#L148

So parent can't be None or otherwise the connection will be None and the whole copy operation becomes impossible.

Are you sure self.drive is None from the driveitem that executes the copy method?

This must be something else.

alejcas avatar Feb 01 '24 09:02 alejcas

First of all: Thank you so much for your time and the effort you put into this project! It is really appreciated.

I think drive.copy does not use the parent, but self.drive instead:

https://github.com/O365/python-o365/blob/417d8cf2e7fa9cea19be0baed197c5f3a9e55a9d/O365/drive.py#L790

The latter one is None in case of a shared folder (at least for me):

grafik

Maybe the connection object is taken from the parent, but the protocol information is taken from self.drive which is denoted parent in the failing method?

jkunczik avatar Feb 04 '24 21:02 jkunczik

Can you provide the code on how you get the shared driveitem please?

alejcas avatar Feb 28 '24 09:02 alejcas