Skip to content

Uploads.upload() polls forever with no timeout and leaks an open file handle #17

Description

@aaronelliotross

What's happening

Uploads.upload() (actionkit/uploads.py:19-34):

def upload(self, file_name, import_page):
    m = MultipartEncoderMonitor.from_fields(
        fields={
            'page': import_page,
            'upload': (file_name, open(file_name, 'rb'), 'text/csv'),
            'autocreate_user_fields': 'false',
        },
        callback=progressing,
    )

    upload_url = self.post(data=m, headers={'Content-Type': m.content_type})

    upload = self.poll(upload_url)
    while not upload['is_completed']:
        upload = self.poll(upload_url)
        time.sleep(1)

Two issues:

  1. No timeout / max-attempt count on the polling loop. If ActionKit's import job never completes (or the is_completed field is never present/true for some reason), this hangs the calling process forever.
  2. The file handle from open(file_name, 'rb') is never explicitly closed. It's only passed into MultipartEncoderMonitor.from_fields, which doesn't take ownership/close it after the request completes.

Suggested fix direction

  • Add a max-attempt count or overall timeout to the polling loop, raising a clear exception (or returning a "still pending" result) if exceeded.
  • Use a with open(file_name, 'rb') as fh: block (or otherwise ensure the handle is closed) around the request.

Test coverage

Pinned (not fixed) by tests/test_uploads.py::test_upload_polls_until_is_completed, which documents the unbounded-loop behavior explicitly in its docstring — it only terminates because the mocked poll() sequence is finite. Should be revisited once a timeout/max-attempts is added.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions