prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  trio.Path.iterdir wrapping is broken
  Given `pathlib.Path.iterdir` returns a generator that does IO access on each iteration, `trio.Path.iterdir` is currently broken given it currently only generates the generator asynchronously (which I suppose is pointless given there is no need for IO at generator creation)
  
  The solution would be to modify  `trio.Path.iterdir` to return an async generator, however this means creating a special case given the current implementation is only an async wrapper on `pathlib.Path.iterdir`.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `trio/_path.py`
  Content:
  ```
  1 from functools import wraps, partial
  2 import os
  3 import types
  4 import pathlib
  5 
  6 import trio
  7 from trio._util import async_wraps, fspath
  8 
  9 __all__ = ['Path']
  10 
  11 
  12 # python3.5 compat: __fspath__ does not exist in 3.5, so unwrap any trio.Path
  13 # being passed to any wrapped method
  14 def unwrap_paths(args):
  15     new_args = []
  16     for arg in args:
  17         if isinstance(arg, Path):
  18             arg = arg._wrapped
  19         new_args.append(arg)
  20     return new_args
  21 
  22 
  23 # re-wrap return value from methods that return new instances of pathlib.Path
  24 def rewrap_path(value):
  25     if isinstance(value, pathlib.Path):
  26         value = Path(value)
  27     return value
  28 
  29 
  30 def _forward_factory(cls, attr_name, attr):
  31     @wraps(attr)
  32     def wrapper(self, *args, **kwargs):
  33         args = unwrap_paths(args)
  34         attr = getattr(self._wrapped, attr_name)
  35         value = attr(*args, **kwargs)
  36         return rewrap_path(value)
  37 
  38     return wrapper
  39 
  40 
  41 def _forward_magic(cls, attr):
  42     sentinel = object()
  43 
  44     @wraps(attr)
  45     def wrapper(self, other=sentinel):
  46         if other is sentinel:
  47             return attr(self._wrapped)
  48         if isinstance(other, cls):
  49             other = other._wrapped
  50         value = attr(self._wrapped, other)
  51         return rewrap_path(value)
  52 
  53     return wrapper
  54 
  55 
  56 def thread_wrapper_factory(cls, meth_name):
  57     @async_wraps(cls, pathlib.Path, meth_name)
  58     async def wrapper(self, *args, **kwargs):
  59         args = unwrap_paths(args)
  60         meth = getattr(self._wrapped, meth_name)
  61         func = partial(meth, *args, **kwargs)
  62         value = await trio.run_sync_in_worker_thread(func)
  63         return rewrap_path(value)
  64 
  65     return wrapper
  66 
  67 
  68 class AsyncAutoWrapperType(type):
  69     def __init__(cls, name, bases, attrs):
  70         super().__init__(name, bases, attrs)
  71 
  72         cls._forward = []
  73         type(cls).generate_forwards(cls, attrs)
  74         type(cls).generate_wraps(cls, attrs)
  75         type(cls).generate_magic(cls, attrs)
  76 
  77     def generate_forwards(cls, attrs):
  78         # forward functions of _forwards
  79         for attr_name, attr in cls._forwards.__dict__.items():
  80             if attr_name.startswith('_') or attr_name in attrs:
  81                 continue
  82 
  83             if isinstance(attr, property):
  84                 cls._forward.append(attr_name)
  85             elif isinstance(attr, types.FunctionType):
  86                 wrapper = _forward_factory(cls, attr_name, attr)
  87                 setattr(cls, attr_name, wrapper)
  88             else:
  89                 raise TypeError(attr_name, type(attr))
  90 
  91     def generate_wraps(cls, attrs):
  92         # generate wrappers for functions of _wraps
  93         for attr_name, attr in cls._wraps.__dict__.items():
  94             if attr_name.startswith('_') or attr_name in attrs:
  95                 continue
  96 
  97             if isinstance(attr, classmethod):
  98                 setattr(cls, attr_name, attr)
  99             elif isinstance(attr, types.FunctionType):
  100                 wrapper = thread_wrapper_factory(cls, attr_name)
  101                 setattr(cls, attr_name, wrapper)
  102             else:
  103                 raise TypeError(attr_name, type(attr))
  104 
  105     def generate_magic(cls, attrs):
  106         # generate wrappers for magic
  107         for attr_name in cls._forward_magic:
  108             attr = getattr(cls._forwards, attr_name)
  109             wrapper = _forward_magic(cls, attr)
  110             setattr(cls, attr_name, wrapper)
  111 
  112 
  113 class Path(metaclass=AsyncAutoWrapperType):
  114     """A :class:`pathlib.Path` wrapper that executes blocking methods in
  115     :meth:`trio.run_sync_in_worker_thread`.
  116 
  117     """
  118 
  119     _wraps = pathlib.Path
  120     _forwards = pathlib.PurePath
  121     _forward_magic = [
  122         '__str__', '__bytes__', '__truediv__', '__rtruediv__', '__eq__',
  123         '__lt__', '__le__', '__gt__', '__ge__'
  124     ]
  125 
  126     def __init__(self, *args):
  127         args = unwrap_paths(args)
  128 
  129         self._wrapped = pathlib.Path(*args)
  130 
  131     def __getattr__(self, name):
  132         if name in self._forward:
  133             value = getattr(self._wrapped, name)
  134             return rewrap_path(value)
  135         raise AttributeError(name)
  136 
  137     def __dir__(self):
  138         return super().__dir__() + self._forward
  139 
  140     def __repr__(self):
  141         return 'trio.Path({})'.format(repr(str(self)))
  142 
  143     def __fspath__(self):
  144         return fspath(self._wrapped)
  145 
  146     @wraps(pathlib.Path.open)
  147     async def open(self, *args, **kwargs):
  148         """Open the file pointed to by the path, like the :func:`trio.open_file`
  149         function does.
  150 
  151         """
  152 
  153         func = partial(self._wrapped.open, *args, **kwargs)
  154         value = await trio.run_sync_in_worker_thread(func)
  155         return trio.wrap_file(value)
  156 
  157 
  158 # The value of Path.absolute.__doc__ makes a reference to
  159 # :meth:~pathlib.Path.absolute, which does not exist. Removing this makes more
  160 # sense than inventing our own special docstring for this.
  161 del Path.absolute.__doc__
  162 
  163 # python3.5 compat
  164 if hasattr(os, 'PathLike'):
  165     os.PathLike.register(Path)
  166
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/trio/_path.py b/trio/_path.py
  --- a/trio/_path.py
  +++ b/trio/_path.py
  @@ -128,6 +128,28 @@
   
           self._wrapped = pathlib.Path(*args)
   
  +    async def iterdir(self):
  +        """
  +        Like :meth:`pathlib.Path.iterdir`, but async.
  +
  +        This is an async method that returns a synchronous iterator, so you
  +        use it like::
  +        
  +           for subpath in await mypath.iterdir():
  +               ...
  +               
  +        Note that it actually loads the whole directory list into memory
  +        immediately, during the initial call. (See `issue #501
  +        <https://github.com/python-trio/trio/issues/501>`__ for discussion.)
  +        
  +        """
  +
  +        def _load_items():
  +            return list(self._wrapped.iterdir())
  +
  +        items = await trio.run_sync_in_worker_thread(_load_items)
  +        return (Path(item) for item in items)
  +
       def __getattr__(self, name):
           if name in self._forward:
               value = getattr(self._wrapped, name)
  
verification_info: {"golden_diff": "diff --git a/trio/_path.py b/trio/_path.py\n--- a/trio/_path.py\n+++ b/trio/_path.py\n@@ -128,6 +128,28 @@\n \n         self._wrapped = pathlib.Path(*args)\n \n+    async def iterdir(self):\n+        \"\"\"\n+        Like :meth:`pathlib.Path.iterdir`, but async.\n+\n+        This is an async method that returns a synchronous iterator, so you\n+        use it like::\n+        \n+           for subpath in await mypath.iterdir():\n+               ...\n+               \n+        Note that it actually loads the whole directory list into memory\n+        immediately, during the initial call. (See `issue #501\n+        <https://github.com/python-trio/trio/issues/501>`__ for discussion.)\n+        \n+        \"\"\"\n+\n+        def _load_items():\n+            return list(self._wrapped.iterdir())\n+\n+        items = await trio.run_sync_in_worker_thread(_load_items)\n+        return (Path(item) for item in items)\n+\n     def __getattr__(self, name):\n         if name in self._forward:\n             value = getattr(self._wrapped, name)\n", "issue": "trio.Path.iterdir wrapping is broken\nGiven `pathlib.Path.iterdir` returns a generator that does IO access on each iteration, `trio.Path.iterdir` is currently broken given it currently only generates the generator asynchronously (which I suppose is pointless given there is no need for IO at generator creation)\r\n\r\nThe solution would be to modify  `trio.Path.iterdir` to return an async generator, however this means creating a special case given the current implementation is only an async wrapper on `pathlib.Path.iterdir`.\n", "before_files": [{"content": "from functools import wraps, partial\nimport os\nimport types\nimport pathlib\n\nimport trio\nfrom trio._util import async_wraps, fspath\n\n__all__ = ['Path']\n\n\n# python3.5 compat: __fspath__ does not exist in 3.5, so unwrap any trio.Path\n# being passed to any wrapped method\ndef unwrap_paths(args):\n    new_args = []\n    for arg in args:\n        if isinstance(arg, Path):\n            arg = arg._wrapped\n        new_args.append(arg)\n    return new_args\n\n\n# re-wrap return value from methods that return new instances of pathlib.Path\ndef rewrap_path(value):\n    if isinstance(value, pathlib.Path):\n        value = Path(value)\n    return value\n\n\ndef _forward_factory(cls, attr_name, attr):\n    @wraps(attr)\n    def wrapper(self, *args, **kwargs):\n        args = unwrap_paths(args)\n        attr = getattr(self._wrapped, attr_name)\n        value = attr(*args, **kwargs)\n        return rewrap_path(value)\n\n    return wrapper\n\n\ndef _forward_magic(cls, attr):\n    sentinel = object()\n\n    @wraps(attr)\n    def wrapper(self, other=sentinel):\n        if other is sentinel:\n            return attr(self._wrapped)\n        if isinstance(other, cls):\n            other = other._wrapped\n        value = attr(self._wrapped, other)\n        return rewrap_path(value)\n\n    return wrapper\n\n\ndef thread_wrapper_factory(cls, meth_name):\n    @async_wraps(cls, pathlib.Path, meth_name)\n    async def wrapper(self, *args, **kwargs):\n        args = unwrap_paths(args)\n        meth = getattr(self._wrapped, meth_name)\n        func = partial(meth, *args, **kwargs)\n        value = await trio.run_sync_in_worker_thread(func)\n        return rewrap_path(value)\n\n    return wrapper\n\n\nclass AsyncAutoWrapperType(type):\n    def __init__(cls, name, bases, attrs):\n        super().__init__(name, bases, attrs)\n\n        cls._forward = []\n        type(cls).generate_forwards(cls, attrs)\n        type(cls).generate_wraps(cls, attrs)\n        type(cls).generate_magic(cls, attrs)\n\n    def generate_forwards(cls, attrs):\n        # forward functions of _forwards\n        for attr_name, attr in cls._forwards.__dict__.items():\n            if attr_name.startswith('_') or attr_name in attrs:\n                continue\n\n            if isinstance(attr, property):\n                cls._forward.append(attr_name)\n            elif isinstance(attr, types.FunctionType):\n                wrapper = _forward_factory(cls, attr_name, attr)\n                setattr(cls, attr_name, wrapper)\n            else:\n                raise TypeError(attr_name, type(attr))\n\n    def generate_wraps(cls, attrs):\n        # generate wrappers for functions of _wraps\n        for attr_name, attr in cls._wraps.__dict__.items():\n            if attr_name.startswith('_') or attr_name in attrs:\n                continue\n\n            if isinstance(attr, classmethod):\n                setattr(cls, attr_name, attr)\n            elif isinstance(attr, types.FunctionType):\n                wrapper = thread_wrapper_factory(cls, attr_name)\n                setattr(cls, attr_name, wrapper)\n            else:\n                raise TypeError(attr_name, type(attr))\n\n    def generate_magic(cls, attrs):\n        # generate wrappers for magic\n        for attr_name in cls._forward_magic:\n            attr = getattr(cls._forwards, attr_name)\n            wrapper = _forward_magic(cls, attr)\n            setattr(cls, attr_name, wrapper)\n\n\nclass Path(metaclass=AsyncAutoWrapperType):\n    \"\"\"A :class:`pathlib.Path` wrapper that executes blocking methods in\n    :meth:`trio.run_sync_in_worker_thread`.\n\n    \"\"\"\n\n    _wraps = pathlib.Path\n    _forwards = pathlib.PurePath\n    _forward_magic = [\n        '__str__', '__bytes__', '__truediv__', '__rtruediv__', '__eq__',\n        '__lt__', '__le__', '__gt__', '__ge__'\n    ]\n\n    def __init__(self, *args):\n        args = unwrap_paths(args)\n\n        self._wrapped = pathlib.Path(*args)\n\n    def __getattr__(self, name):\n        if name in self._forward:\n            value = getattr(self._wrapped, name)\n            return rewrap_path(value)\n        raise AttributeError(name)\n\n    def __dir__(self):\n        return super().__dir__() + self._forward\n\n    def __repr__(self):\n        return 'trio.Path({})'.format(repr(str(self)))\n\n    def __fspath__(self):\n        return fspath(self._wrapped)\n\n    @wraps(pathlib.Path.open)\n    async def open(self, *args, **kwargs):\n        \"\"\"Open the file pointed to by the path, like the :func:`trio.open_file`\n        function does.\n\n        \"\"\"\n\n        func = partial(self._wrapped.open, *args, **kwargs)\n        value = await trio.run_sync_in_worker_thread(func)\n        return trio.wrap_file(value)\n\n\n# The value of Path.absolute.__doc__ makes a reference to\n# :meth:~pathlib.Path.absolute, which does not exist. Removing this makes more\n# sense than inventing our own special docstring for this.\ndel Path.absolute.__doc__\n\n# python3.5 compat\nif hasattr(os, 'PathLike'):\n    os.PathLike.register(Path)\n", "path": "trio/_path.py"}], "after_files": [{"content": "from functools import wraps, partial\nimport os\nimport types\nimport pathlib\n\nimport trio\nfrom trio._util import async_wraps, fspath\n\n__all__ = ['Path']\n\n\n# python3.5 compat: __fspath__ does not exist in 3.5, so unwrap any trio.Path\n# being passed to any wrapped method\ndef unwrap_paths(args):\n    new_args = []\n    for arg in args:\n        if isinstance(arg, Path):\n            arg = arg._wrapped\n        new_args.append(arg)\n    return new_args\n\n\n# re-wrap return value from methods that return new instances of pathlib.Path\ndef rewrap_path(value):\n    if isinstance(value, pathlib.Path):\n        value = Path(value)\n    return value\n\n\ndef _forward_factory(cls, attr_name, attr):\n    @wraps(attr)\n    def wrapper(self, *args, **kwargs):\n        args = unwrap_paths(args)\n        attr = getattr(self._wrapped, attr_name)\n        value = attr(*args, **kwargs)\n        return rewrap_path(value)\n\n    return wrapper\n\n\ndef _forward_magic(cls, attr):\n    sentinel = object()\n\n    @wraps(attr)\n    def wrapper(self, other=sentinel):\n        if other is sentinel:\n            return attr(self._wrapped)\n        if isinstance(other, cls):\n            other = other._wrapped\n        value = attr(self._wrapped, other)\n        return rewrap_path(value)\n\n    return wrapper\n\n\ndef thread_wrapper_factory(cls, meth_name):\n    @async_wraps(cls, pathlib.Path, meth_name)\n    async def wrapper(self, *args, **kwargs):\n        args = unwrap_paths(args)\n        meth = getattr(self._wrapped, meth_name)\n        func = partial(meth, *args, **kwargs)\n        value = await trio.run_sync_in_worker_thread(func)\n        return rewrap_path(value)\n\n    return wrapper\n\n\nclass AsyncAutoWrapperType(type):\n    def __init__(cls, name, bases, attrs):\n        super().__init__(name, bases, attrs)\n\n        cls._forward = []\n        type(cls).generate_forwards(cls, attrs)\n        type(cls).generate_wraps(cls, attrs)\n        type(cls).generate_magic(cls, attrs)\n\n    def generate_forwards(cls, attrs):\n        # forward functions of _forwards\n        for attr_name, attr in cls._forwards.__dict__.items():\n            if attr_name.startswith('_') or attr_name in attrs:\n                continue\n\n            if isinstance(attr, property):\n                cls._forward.append(attr_name)\n            elif isinstance(attr, types.FunctionType):\n                wrapper = _forward_factory(cls, attr_name, attr)\n                setattr(cls, attr_name, wrapper)\n            else:\n                raise TypeError(attr_name, type(attr))\n\n    def generate_wraps(cls, attrs):\n        # generate wrappers for functions of _wraps\n        for attr_name, attr in cls._wraps.__dict__.items():\n            if attr_name.startswith('_') or attr_name in attrs:\n                continue\n\n            if isinstance(attr, classmethod):\n                setattr(cls, attr_name, attr)\n            elif isinstance(attr, types.FunctionType):\n                wrapper = thread_wrapper_factory(cls, attr_name)\n                setattr(cls, attr_name, wrapper)\n            else:\n                raise TypeError(attr_name, type(attr))\n\n    def generate_magic(cls, attrs):\n        # generate wrappers for magic\n        for attr_name in cls._forward_magic:\n            attr = getattr(cls._forwards, attr_name)\n            wrapper = _forward_magic(cls, attr)\n            setattr(cls, attr_name, wrapper)\n\n\nclass Path(metaclass=AsyncAutoWrapperType):\n    \"\"\"A :class:`pathlib.Path` wrapper that executes blocking methods in\n    :meth:`trio.run_sync_in_worker_thread`.\n\n    \"\"\"\n\n    _wraps = pathlib.Path\n    _forwards = pathlib.PurePath\n    _forward_magic = [\n        '__str__', '__bytes__', '__truediv__', '__rtruediv__', '__eq__',\n        '__lt__', '__le__', '__gt__', '__ge__'\n    ]\n\n    def __init__(self, *args):\n        args = unwrap_paths(args)\n\n        self._wrapped = pathlib.Path(*args)\n\n    async def iterdir(self):\n        \"\"\"\n        Like :meth:`pathlib.Path.iterdir`, but async.\n\n        This is an async method that returns a synchronous iterator, so you\n        use it like::\n        \n           for subpath in await mypath.iterdir():\n               ...\n               \n        Note that it actually loads the whole directory list into memory\n        immediately, during the initial call. (See `issue #501\n        <https://github.com/python-trio/trio/issues/501>`__ for discussion.)\n        \n        \"\"\"\n\n        def _load_items():\n            return list(self._wrapped.iterdir())\n\n        items = await trio.run_sync_in_worker_thread(_load_items)\n        return (Path(item) for item in items)\n\n    def __getattr__(self, name):\n        if name in self._forward:\n            value = getattr(self._wrapped, name)\n            return rewrap_path(value)\n        raise AttributeError(name)\n\n    def __dir__(self):\n        return super().__dir__() + self._forward\n\n    def __repr__(self):\n        return 'trio.Path({})'.format(repr(str(self)))\n\n    def __fspath__(self):\n        return fspath(self._wrapped)\n\n    @wraps(pathlib.Path.open)\n    async def open(self, *args, **kwargs):\n        \"\"\"Open the file pointed to by the path, like the :func:`trio.open_file`\n        function does.\n\n        \"\"\"\n\n        func = partial(self._wrapped.open, *args, **kwargs)\n        value = await trio.run_sync_in_worker_thread(func)\n        return trio.wrap_file(value)\n\n\n# The value of Path.absolute.__doc__ makes a reference to\n# :meth:~pathlib.Path.absolute, which does not exist. Removing this makes more\n# sense than inventing our own special docstring for this.\ndel Path.absolute.__doc__\n\n# python3.5 compat\nif hasattr(os, 'PathLike'):\n    os.PathLike.register(Path)\n", "path": "trio/_path.py"}]}