odwyersoftware / mega.py

Python library for the https://mega.nz/ API.
https://github.com/odwyersoftware/mega.py
Apache License 2.0
350 stars 170 forks source link

Error with create_folder #15

Open olliechick opened 4 years ago

olliechick commented 4 years ago

When trying to create a folder, I got an error. My stacktrace is below, from my line of code that creates the folder down. The variables STORIES_DIR is "stories", MEGA_SEP is "/", and folder_name was a string of alphabetic characters.

Stacktrace:

m.create_folder(STORIES_DIR + MEGA_SEP + folder_name)
File "/app/.heroku/python/lib/python3.6/site-packages/mega/mega.py", line 884, in create_folder
existing_node_id = self.find_path_descriptor(directory_name)
File "/app/.heroku/python/lib/python3.6/site-packages/mega/mega.py", line 306, in find_path_descriptor
and file[1]['a']['n'] == foldername):
TypeError: string indices must be integers

My Mega account's directory structure looked like this:

stories
   ⮡ folder1
   ⮡ folder2

Note that folder1 and folder2 actually have different names, made up of alphabetic characters.

knowledgeorange commented 4 years ago

I think that you have done somthing wrong in the way you passed the folder name, try to create one string and then pass it to the function.

olliechick commented 4 years ago

I tried that, but it still doesn't work. I ran this function:

def test_create_folder():
    mega = Mega()
    email = os.environ[ENV_MEGA_EMAIL]
    password = os.environ[ENV_MEGA_PASSWORD]
    m = mega.login(email, password)
    print(m.get_storage_space(giga=True))
    m.create_folder("testfolder")

But it still gave me the stacktrace:

Traceback (most recent call last):
  File "C:/Users/ollie/Documents/ig-story-saver/ig_story_saver.py", line 189, in <module>
    test_create_folder()
  File "C:/Users/ollie/Documents/ig-story-saver/ig_story_saver.py", line 167, in test_create_folder
    m.create_folder("testfolder")
  File "C:\Users\ollie\Documents\ig-story-saver\venv\lib\site-packages\mega\mega.py", line 884, in create_folder
    existing_node_id = self.find_path_descriptor(directory_name)
  File "C:\Users\ollie\Documents\ig-story-saver\venv\lib\site-packages\mega\mega.py", line 306, in find_path_descriptor
    and file[1]['a']['n'] == foldername):
TypeError: string indices must be integers

(The output above the stacktrace was {'used': 1.0925600370392203, 'total': 50.0}.)

olliechick commented 4 years ago

I think I figured it out - I had some duplicates in my Mega account (multiples files with the same name in the same folder). Deleting these and removing them from the rubbish bin fixed the issue.

It would be good to have some kind of descriptive error message for this situation.

mouhandalkadri commented 4 years ago

I have same problem here even though I tried to create folder with the same name used in the docs

this is the error

  and file[1]['a']['n'] == foldername):
TypeError: string indices must be integers
refidAc commented 4 years ago

also same problem, I'm only passing in a simple string to test, no duplicate folders. In:

m = mega.login(email, password)
m.create_folder('test')

Out:

File "/.pyenv/versions/3.7.0/lib/python3.7/site-packages/mega/mega.py", line 306, in find_path_descriptor
    and file[1]['a']['n'] == foldername):
TypeError: string indices must be integers
refidAc commented 4 years ago

I have same problem here even though I tried to create folder with the same name used in the docs

this is the error

  and file[1]['a']['n'] == foldername):
TypeError: string indices must be integers

also same problem, I'm only passing in a simple string to test, no duplicate folders. In:

m = mega.login(email, password)
m.create_folder('test')

Out:

File "/.pyenv/versions/3.7.0/lib/python3.7/site-packages/mega/mega.py", line 306, in find_path_descriptor
    and file[1]['a']['n'] == foldername):
TypeError: string indices must be integers

Ok, so a temporary fix, as long as you're sure the folder you're creating is unique, I think is to comment out these lines in mega.py: LINES: 884 - 887

existing_node_id = self.find_path_descriptor(directory_name)
if existing_node_id:
    folder_node_ids[idx] = existing_node_id
    continue
purshothamn commented 4 years ago

yep that fixed the issue

shorts7wound commented 3 years ago

existing_node_id = self.find_path_descriptor(directory_name) if existing_node_id: folder_node_ids[idx] = existing_node_id continue

i actually had same problem and this fixed it , but if try to create same subfolder it also recreate parent folder twice and it keeps doing it everytime

spacebares commented 2 years ago

how are we in mid 2022 and this is still a problem? commenting those lines out fixes it but cmon..

yassinerh28 commented 1 year ago

Summary

The problem is in the find_path_descriptor function (line: 289) in the mega.py package.

Debugging

  1. I commented lines 305:309
    # if (file[1]['a'] and file[1]['t']
    #         and file[1]['a']['n'] == foldername):
    #     if parent_desc == file[1]['p']:
    #         parent_desc = file[0]
    #         found = True
  2. Above that (line: 305) I inserted the line below to return file[1]['a'] with its type
    print(type(file[1]['a']), file[1]['a'])
  3. I called the find_path_descriptor function
    m.find_path_descriptor("test")

    here is the output: (I replaced the values with 'name-i', 'string-i' and 'value-i' to hide my mega files' information)

    <class 'dict'> {'n': 'name-1'}
    <class 'dict'> {'n': 'name-2'}
    <class 'dict'> {'n': 'name-3'}
    <class 'dict'> {'c': 'value-4', 'n': 'name-4'}
    <class 'dict'> {'c': 'value-5', 'n': 'name-5'}
    <class 'dict'> {'c': 'value-6', 'n': 'name-6'}
    ...
    <class 'dict'> {'c': 'value-23', 'n': 'name-23'}
    <class 'dict'> {'c': 'value-24', 'n': 'name-24'}
    <class 'str'> 'string-25'
    <class 'str'> 'string-26'
    <class 'str'> 'string-27'

    As you see, sometimes file[1]['a'] is a <class 'dict'> but sometimes it's a <class 'str'>. The <class 'str'> ones cause the TypeError: string indices must be integers.

You get the TypeError: string indices must be integers error when you try to access a character using its string value rather the index number.

That's exactly what's happening when find_path_descriptor tries to access the 'n' key like this: file[1]['a']['n'] (because it expects file[1]['a'] to be a <class 'dict'>). That's why you get the error.

Fix

  1. Don't forget to undo step 1 and step 2 before you apply the fix

    • Remove the print line (line: 305)
    • Uncomment the lines 305:309
  2. Insert the line below at the top of the for statement's body (at line: 305) to verify if file[1]['a'] is a <class 'dict'> or else just skip it with continue.

    if (not (type(file[1]['a']) is dict)):
    continue

    Now your find_path_descriptor function should look like this:

    def find_path_descriptor(self, path, files=()):
        """
        Find descriptor of folder inside a path. i.e.: folder1/folder2/folder3
        Params:
            path, string like folder1/folder2/folder3
        Return:
            Descriptor (str) of folder3 if exists, None otherwise
        """
        paths = path.split('/')
    
        files = files or self.get_files()
        parent_desc = self.root_id
        found = False
        for foldername in paths:
            if foldername != '':
                for file in files.items():
                    if (not (type(file[1]['a']) is dict)):
                        continue
                    if (file[1]['a'] and file[1]['t']
                            and file[1]['a']['n'] == foldername):
                        if parent_desc == file[1]['p']:
                            parent_desc = file[0]
                            found = True
                if found:
                    found = False
                else:
                    return None
        return parent_desc