# Buggy code
async def poll(self):
    """
    Check if the pod is still running.

    Uses the same interface as subprocess.Popen.poll(): if the pod is
    still running, returns None.  If the pod has exited, return the
    exit code if we can determine it, or 1 if it has exited but we
    don't know how.  These are the return values JupyterHub expects.

    Note that a clean exit will have an exit code of zero, so it is
    necessary to check that the returned value is None, rather than
    just Falsy, to determine that the pod is still running.
    """
    # have to wait for first load of data before we have a valid answer
    if not self.pod_reflector.first_load_future.done():
        await self.pod_reflector.first_load_future
    data = self.pod_reflector.pods.get(self.pod_name, None)
    if data is not None:
        if data["status"]["phase"] == "Pending":
            return None
        ctr_stat = data["status"].get("containerStatuses")
        if ctr_stat is None:  # No status, no container (we hope)
            # This seems to happen when a pod is idle-culled.
            return 1
        for c in ctr_stat:
            # return exit code if notebook container has terminated
            if c["name"] == "notebook":
                if "terminated" in c["state"]:
                    # call self.stop to delete the pod
                    if self.delete_stopped_pods:
                        await self.stop(now=True)
                    return c["state"]["terminated"]["exitCode"]
                break
        # None means pod is running or starting up
        return None
    # pod doesn't exist or has been deleted
    return 1


# Traceback (TypeError)
Traceback (most recent call last):
File "/usr/local/lib/python3.8/dist-packages/jupyterhub/app.py", line 2032, in check_spawner
status = await spawner.poll()
File "/usr/local/lib/python3.8/dist-packages/kubespawner/spawner.py", line 1610, in poll
await self.pod_reflector.first_load_future
TypeError: object Future can't be used in 'await' expression

# Fixed code
async def poll(self):
    """
    Check if the pod is still running.

    Uses the same interface as subprocess.Popen.poll(): if the pod is
    still running, returns None.  If the pod has exited, return the
    exit code if we can determine it, or 1 if it has exited but we
    don't know how.  These are the return values JupyterHub expects.

    Note that a clean exit will have an exit code of zero, so it is
    necessary to check that the returned value is None, rather than
    just Falsy, to determine that the pod is still running.
    """
    # have to wait for first load of data before we have a valid answer
    if not self.pod_reflector.first_load_future.done():
        await asyncio.wrap_future(self.pod_reflector.first_load_future)
    data = self.pod_reflector.pods.get(self.pod_name, None)
    if data is not None:
        if data["status"]["phase"] == "Pending":
            return None
        ctr_stat = data["status"].get("containerStatuses")
        if ctr_stat is None:  # No status, no container (we hope)
            # This seems to happen when a pod is idle-culled.
            return 1
        for c in ctr_stat:
            # return exit code if notebook container has terminated
            if c["name"] == "notebook":
                if "terminated" in c["state"]:
                    # call self.stop to delete the pod
                    if self.delete_stopped_pods:
                        await self.stop(now=True)
                    return c["state"]["terminated"]["exitCode"]
                break
        # None means pod is running or starting up
        return None
    # pod doesn't exist or has been deleted
    return 1