Doist / todoist-python

DEPRECATED The official Todoist Python API library
MIT License
535 stars 73 forks source link

'str' object has no attribute 'get' in labels.py #83

Open rosenpin opened 3 years ago

rosenpin commented 3 years ago

Hi, I'm trying to use the API and it seems that in some circumstances I get this error when trying to get a label:

File "/home/ubuntu/.local/lib/python3.8/site-packages/todoist/managers/labels.py", line 72, in get
    if obj.get("label"):
AttributeError: 'str' object has no attribute 'get'

The code part in question is the following:

    def get(self, label_id):
        """
        Gets an existing label.
        """
        params = {"token": self.token, "label_id": label_id}
        obj = self.api._get("labels/get", params=params)
        if obj and "error" in obj:
            return None
        data = {"labels": []}
        if obj.get("label"):
            data["labels"].append(obj.get("label"))
        self.api._update_state(data)
        return obj

The problematic line is this:

        if obj.get("label"):

Seems like in some situations the obj returned from self.api._get is a string object?\ Kind of weird, anyway this causes an exception and obviously doesn't return the label

Update:

Seems like it only happens when I'm trying to access labels concurrently

Update 2:

Managed to solve it for my case for now by avoiding concurrently accessing labels, I didn't check if it happens when trying to access the same label or 2 labels in parallel in general.

PotHix commented 3 years ago

@rosenpin can you please provide a sample code to reproduce it?

rosenpin commented 3 years ago

If it doesn't crash try running it again or with more iterations than 5

Example code

from threading import Thread

from todoist import TodoistAPI

def test(api, labels):
    for label in labels:
        Thread(target=lambda: print(api.labels.get(label_id=label["id"]))).start()

def main():
    api = TodoistAPI(token=YOUR_TOKEN)
    api.reset_state()
    api.sync()
    labels = api.labels.all()
    for i in range(5):
        Thread(target=lambda: test(api=api, labels=labels)).start()

if __name__ == '__main__':
    main()

Example log:

test.py

1d+
⏲1h
1d+
⏲30m
⏲3h
⏲5h
⏲5h
⏲15m
1d+
⏲5h
⏲8h
Calendar
1d+
⏲2h
⏲15m
1d+
Calendar
Calendar
⏲1h
Calendar
⏲15m
⏲4h
⏲15m
⏲15m
⏲1h
⏲4h
⏲30m
⏲2h
⏲2h
⏲1h
⏲30m
⏲7h
⏲1h
⏲2h
⏲3h
⏲6h
⏲30m
Calendar
⏲5h
⏲3h
⏲30m
⏲2h
⏲4h
⏲6h
⏲5h
⏲7h
⏲4h
⏲3h
⏲8h
Exception in thread Thread-50:
Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/home/tomer/Projects/Python/durations-for-todoist/test.py", line 8, in <lambda>
    Thread(target=lambda: print(api.labels.get(label_id=label["id"])["label"]["name"])).start()
  File "/home/tomer/.local/lib/python3.8/site-packages/todoist/managers/labels.py", line 72, in get
    if obj.get("label"):
AttributeError: 'str' object has no attribute 'get'
Exception in thread Thread-57:
Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
Exception in thread Thread-60:
Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)    self.run()
  File "/usr/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/home/tomer/Projects/Python/durations-for-todoist/test.py", line 8, in <lambda>
    Thread(target=lambda: print(api.labels.get(label_id=label["id"])["label"]["name"])).start()
  File "/home/tomer/.local/lib/python3.8/site-packages/todoist/managers/labels.py", line 72, in get
    if obj.get("label"):
AttributeError: 'str' object has no attribute 'get'

  File "/home/tomer/Projects/Python/durations-for-todoist/test.py", line 8, in <lambda>
Exception in thread Thread-61:
Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/home/tomer/Projects/Python/durations-for-todoist/test.py", line 8, in <lambda>
    Thread(target=lambda: print(api.labels.get(label_id=label["id"])["label"]["name"])).start()
  File "/home/tomer/.local/lib/python3.8/site-packages/todoist/managers/labels.py", line 72, in get
    if obj.get("label"):
AttributeError: 'str' object has no attribute 'get'
Exception in thread Thread-48:
Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.8/threading.py", line 870, in run
Exception in thread Thread-58:
Traceback (most recent call last):
Exception in thread Thread-53:
Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    Thread(target=lambda: print(api.labels.get(label_id=label["id"])["label"]["name"])).start()        self.run()
self._target(*self._args, **self._kwargs)
  File "/usr/lib/python3.8/threading.py", line 870, in run
  File "/home/tomer/Projects/Python/durations-for-todoist/test.py", line 8, in <lambda>

  File "/home/tomer/.local/lib/python3.8/site-packages/todoist/managers/labels.py", line 72, in get
self.run()
  File "/usr/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/home/tomer/Projects/Python/durations-for-todoist/test.py", line 8, in <lambda>
    if obj.get("label"):
AttributeError: 'str' object has no attribute 'get'
    Thread(target=lambda: print(api.labels.get(label_id=label["id"])["label"]["name"])).start()
  File "/home/tomer/.local/lib/python3.8/site-packages/todoist/managers/labels.py", line 72, in get
    if obj.get("label"):
AttributeError: 'str' object has no attribute 'get'
    self._target(*self._args, **self._kwargs)
  File "/home/tomer/Projects/Python/durations-for-todoist/test.py", line 8, in <lambda>
    Thread(target=lambda: print(api.labels.get(label_id=label["id"])["label"]["name"])).start()
  File "/home/tomer/.local/lib/python3.8/site-packages/todoist/managers/labels.py", line 72, in get
    if obj.get("label"):
AttributeError: 'str' object has no attribute 'get'
    Thread(target=lambda: print(api.labels.get(label_id=label["id"])["label"]["name"])).start()
  File "/home/tomer/.local/lib/python3.8/site-packages/todoist/managers/labels.py", line 72, in get
    if obj.get("label"):
AttributeError: 'str' object has no attribute 'get'
Exception in thread Thread-65:
Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/home/tomer/Projects/Python/durations-for-todoist/test.py", line 8, in <lambda>
    Thread(target=lambda: print(api.labels.get(label_id=label["id"])["label"]["name"])).start()
  File "/home/tomer/.local/lib/python3.8/site-packages/todoist/managers/labels.py", line 72, in get
    if obj.get("label"):
AttributeError: 'str' object has no attribute 'get'
Exception in thread Thread-59:
Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/home/tomer/Projects/Python/durations-for-todoist/test.py", line 8, in <lambda>
    Thread(target=lambda: print(api.labels.get(label_id=label["id"])["label"]["name"])).start()
  File "/home/tomer/.local/lib/python3.8/site-packages/todoist/managers/labels.py", line 72, in get
    if obj.get("label"):
AttributeError: 'str' object has no attribute 'get'
⏲7h
⏲7h
⏲7h
⏲️focus
⏲8h
⏲️focus
⏲️focus

Process finished with exit code 0
aprowe commented 3 years ago

I too am getting this error, only on some label requests.

import todoist
api = todoist.TodoistAPI("<key>")

for item in api.items.all():
   for label in item['labels']:
      api.labels.get(label)
PotHix commented 3 years ago

Just want to let everyone know that we are aware of this error. It's not just something related to this library but related to some changes we are doing at the API level. The library is using an endpoint that is not publicly documented and this endpoint is already using a new format.

We are discussing what will be the next steps and will fix the library as soon as we get to a conclusion. :+1:

c99koder commented 3 years ago

Having a similar issue when trying to fetch a Project using the parent_project_id of an event from the Activity API, not sure if it's the same issue or if I should open a new ticket:

Traceback (most recent call last):
  File "./Todoist.py", line 64, in <module>
    project = api.projects.get(event['parent_project_id'])
  File "/ext/home/pi/.local/lib/python3.8/site-packages/todoist/managers/projects.py", line 152, in get
    if obj.get('project'):
AttributeError: 'str' object has no attribute 'get'

I suspect it's related to completing a task inside a section inside a project

PotHix commented 3 years ago

@c99koder this is probably related to a problem we're having at the moment not exactly this issue.

c99koder commented 3 years ago

@PotHix Yes, it seems to be working again now the outage has been resolved. Thanks!