summaryrefslogtreecommitdiffstats
path: root/venv/lib/python3.9/site-packages/trio/_path.py
diff options
context:
space:
mode:
authornoptuno <repollo.marrero@gmail.com>2023-04-28 02:29:30 +0200
committernoptuno <repollo.marrero@gmail.com>2023-04-28 02:29:30 +0200
commit355dee533bb34a571b9367820a63cccb668cf866 (patch)
tree838af886b4fec07320aeb10f0d1e74ba79e79b5c /venv/lib/python3.9/site-packages/trio/_path.py
parentadded pyproject.toml file (diff)
downloadgpt4free-355dee533bb34a571b9367820a63cccb668cf866.tar
gpt4free-355dee533bb34a571b9367820a63cccb668cf866.tar.gz
gpt4free-355dee533bb34a571b9367820a63cccb668cf866.tar.bz2
gpt4free-355dee533bb34a571b9367820a63cccb668cf866.tar.lz
gpt4free-355dee533bb34a571b9367820a63cccb668cf866.tar.xz
gpt4free-355dee533bb34a571b9367820a63cccb668cf866.tar.zst
gpt4free-355dee533bb34a571b9367820a63cccb668cf866.zip
Diffstat (limited to 'venv/lib/python3.9/site-packages/trio/_path.py')
-rw-r--r--venv/lib/python3.9/site-packages/trio/_path.py206
1 files changed, 206 insertions, 0 deletions
diff --git a/venv/lib/python3.9/site-packages/trio/_path.py b/venv/lib/python3.9/site-packages/trio/_path.py
new file mode 100644
index 00000000..4077c449
--- /dev/null
+++ b/venv/lib/python3.9/site-packages/trio/_path.py
@@ -0,0 +1,206 @@
+# type: ignore
+
+from functools import wraps, partial
+import os
+import types
+import pathlib
+
+import trio
+from trio._util import async_wraps, Final
+
+
+# re-wrap return value from methods that return new instances of pathlib.Path
+def rewrap_path(value):
+ if isinstance(value, pathlib.Path):
+ value = Path(value)
+ return value
+
+
+def _forward_factory(cls, attr_name, attr):
+ @wraps(attr)
+ def wrapper(self, *args, **kwargs):
+ attr = getattr(self._wrapped, attr_name)
+ value = attr(*args, **kwargs)
+ return rewrap_path(value)
+
+ return wrapper
+
+
+def _forward_magic(cls, attr):
+ sentinel = object()
+
+ @wraps(attr)
+ def wrapper(self, other=sentinel):
+ if other is sentinel:
+ return attr(self._wrapped)
+ if isinstance(other, cls):
+ other = other._wrapped
+ value = attr(self._wrapped, other)
+ return rewrap_path(value)
+
+ return wrapper
+
+
+def iter_wrapper_factory(cls, meth_name):
+ @async_wraps(cls, cls._wraps, meth_name)
+ async def wrapper(self, *args, **kwargs):
+ meth = getattr(self._wrapped, meth_name)
+ func = partial(meth, *args, **kwargs)
+ # Make sure that the full iteration is performed in the thread
+ # by converting the generator produced by pathlib into a list
+ items = await trio.to_thread.run_sync(lambda: list(func()))
+ return (rewrap_path(item) for item in items)
+
+ return wrapper
+
+
+def thread_wrapper_factory(cls, meth_name):
+ @async_wraps(cls, cls._wraps, meth_name)
+ async def wrapper(self, *args, **kwargs):
+ meth = getattr(self._wrapped, meth_name)
+ func = partial(meth, *args, **kwargs)
+ value = await trio.to_thread.run_sync(func)
+ return rewrap_path(value)
+
+ return wrapper
+
+
+def classmethod_wrapper_factory(cls, meth_name):
+ @classmethod
+ @async_wraps(cls, cls._wraps, meth_name)
+ async def wrapper(cls, *args, **kwargs):
+ meth = getattr(cls._wraps, meth_name)
+ func = partial(meth, *args, **kwargs)
+ value = await trio.to_thread.run_sync(func)
+ return rewrap_path(value)
+
+ return wrapper
+
+
+class AsyncAutoWrapperType(Final):
+ def __init__(cls, name, bases, attrs):
+ super().__init__(name, bases, attrs)
+
+ cls._forward = []
+ type(cls).generate_forwards(cls, attrs)
+ type(cls).generate_wraps(cls, attrs)
+ type(cls).generate_magic(cls, attrs)
+ type(cls).generate_iter(cls, attrs)
+
+ def generate_forwards(cls, attrs):
+ # forward functions of _forwards
+ for attr_name, attr in cls._forwards.__dict__.items():
+ if attr_name.startswith("_") or attr_name in attrs:
+ continue
+
+ if isinstance(attr, property):
+ cls._forward.append(attr_name)
+ elif isinstance(attr, types.FunctionType):
+ wrapper = _forward_factory(cls, attr_name, attr)
+ setattr(cls, attr_name, wrapper)
+ else:
+ raise TypeError(attr_name, type(attr))
+
+ def generate_wraps(cls, attrs):
+ # generate wrappers for functions of _wraps
+ for attr_name, attr in cls._wraps.__dict__.items():
+ # .z. exclude cls._wrap_iter
+ if attr_name.startswith("_") or attr_name in attrs:
+ continue
+ if isinstance(attr, classmethod):
+ wrapper = classmethod_wrapper_factory(cls, attr_name)
+ setattr(cls, attr_name, wrapper)
+ elif isinstance(attr, types.FunctionType):
+ wrapper = thread_wrapper_factory(cls, attr_name)
+ setattr(cls, attr_name, wrapper)
+ else:
+ raise TypeError(attr_name, type(attr))
+
+ def generate_magic(cls, attrs):
+ # generate wrappers for magic
+ for attr_name in cls._forward_magic:
+ attr = getattr(cls._forwards, attr_name)
+ wrapper = _forward_magic(cls, attr)
+ setattr(cls, attr_name, wrapper)
+
+ def generate_iter(cls, attrs):
+ # generate wrappers for methods that return iterators
+ for attr_name, attr in cls._wraps.__dict__.items():
+ if attr_name in cls._wrap_iter:
+ wrapper = iter_wrapper_factory(cls, attr_name)
+ setattr(cls, attr_name, wrapper)
+
+
+class Path(metaclass=AsyncAutoWrapperType):
+ """A :class:`pathlib.Path` wrapper that executes blocking methods in
+ :meth:`trio.to_thread.run_sync`.
+
+ """
+
+ _wraps = pathlib.Path
+ _forwards = pathlib.PurePath
+ _forward_magic = [
+ "__str__",
+ "__bytes__",
+ "__truediv__",
+ "__rtruediv__",
+ "__eq__",
+ "__lt__",
+ "__le__",
+ "__gt__",
+ "__ge__",
+ "__hash__",
+ ]
+ _wrap_iter = ["glob", "rglob", "iterdir"]
+
+ def __init__(self, *args):
+ self._wrapped = pathlib.Path(*args)
+
+ def __getattr__(self, name):
+ if name in self._forward:
+ value = getattr(self._wrapped, name)
+ return rewrap_path(value)
+ raise AttributeError(name)
+
+ def __dir__(self):
+ return super().__dir__() + self._forward
+
+ def __repr__(self):
+ return "trio.Path({})".format(repr(str(self)))
+
+ def __fspath__(self):
+ return os.fspath(self._wrapped)
+
+ @wraps(pathlib.Path.open)
+ async def open(self, *args, **kwargs):
+ """Open the file pointed to by the path, like the :func:`trio.open_file`
+ function does.
+
+ """
+
+ func = partial(self._wrapped.open, *args, **kwargs)
+ value = await trio.to_thread.run_sync(func)
+ return trio.wrap_file(value)
+
+
+Path.iterdir.__doc__ = """
+ 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.)
+
+"""
+
+# The value of Path.absolute.__doc__ makes a reference to
+# :meth:~pathlib.Path.absolute, which does not exist. Removing this makes more
+# sense than inventing our own special docstring for this.
+del Path.absolute.__doc__
+
+os.PathLike.register(Path)