Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
ionelmc committed Mar 16, 2021
1 parent 3cfb0e8 commit c4ed607
Show file tree
Hide file tree
Showing 8 changed files with 1,873 additions and 87 deletions.
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ markers =
xfail_simple: Expected test to fail on the `simple` implementation.
addopts =
-ra
--strict
--strict-markers
--ignore=docs/conf.py
--ignore=setup.py
--ignore=ci
Expand Down
6 changes: 3 additions & 3 deletions src/lazy_object_proxy/cext.c
Original file line number Diff line number Diff line change
Expand Up @@ -1286,7 +1286,7 @@ static PyObject *Proxy_await(ProxyObject *self)
return (*meth)(wrapped);
}

PyErr_Format(PyExc_TypeError, " %.100s is missing the __await__ method", type->tp_name);
PyErr_Format(PyExc_TypeError, "%.100s is missing the __await__ method", type->tp_name);
return NULL;
}

Expand All @@ -1308,7 +1308,7 @@ static PyObject *Proxy_aiter(ProxyObject *self)
return (*meth)(wrapped);
}

PyErr_Format(PyExc_TypeError, " %.100s is missing the __aiter__ method", type->tp_name);
PyErr_Format(PyExc_TypeError, "%.100s is missing the __aiter__ method", type->tp_name);
return NULL;
}

Expand All @@ -1331,7 +1331,7 @@ static PyObject *Proxy_anext(ProxyObject *self)
return (*meth)(wrapped);
}

PyErr_Format(PyExc_TypeError, " %.100s is missing the __anext__ method", type->tp_name);
PyErr_Format(PyExc_TypeError, "%.100s is missing the __anext__ method", type->tp_name);
return NULL;
}

Expand Down
17 changes: 10 additions & 7 deletions src/lazy_object_proxy/simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,14 +260,17 @@ def __reduce_ex__(self, protocol):
def __aiter__(self):
return self.__wrapped__.__aiter__()

async def __anext__(self):
return await self.__wrapped__.__anext__()
def __anext__(self):
return self.__wrapped__.__anext__()

def __await__(self):
return await self.__wrapped__
if hasattr(self.__wrapped__, '__await__'):
return self.__wrapped__.__await__()
else:
return iter(self.__wrapped__)

async def __aenter__(self):
return await self.__wrapped__.__aenter__()
def __aenter__(self):
return self.__wrapped__.__aenter__()

async def __aexit__(self, *args, **kwargs):
return await self.__wrapped__.__aexit__(*args, **kwargs)
def __aexit__(self, *args, **kwargs):
return self.__wrapped__.__aexit__(*args, **kwargs)
30 changes: 21 additions & 9 deletions src/lazy_object_proxy/slots.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import operator
from types import GeneratorType, CoroutineType

from .compat import PY2
from .compat import PY3
Expand Down Expand Up @@ -414,7 +415,14 @@ def __exit__(self, *args, **kwargs):
return self.__wrapped__.__exit__(*args, **kwargs)

def __iter__(self):
return iter(self.__wrapped__)
if hasattr(self.__wrapped__, '__await__'):
return self.__wrapped__.__await__()
else:
# raise TypeError("'coroutine' object is not iterable")
return iter(self.__wrapped__)

def __next__(self):
return next(self.__wrapped__)

def __call__(self, *args, **kwargs):
return self.__wrapped__(*args, **kwargs)
Expand All @@ -426,16 +434,20 @@ def __reduce_ex__(self, protocol):
return identity, (self.__wrapped__,)

def __aiter__(self):
return self.__wrapped__.__aiter__()

def __await__(self):
return self.__wrapped__.__await__()
return self

async def __anext__(self):
return await self.__wrapped__.__anext__()

async def __aenter__(self):
return await self.__wrapped__.__aenter__()
def __await__(self):
if hasattr(self.__wrapped__, '__await__'):
return self.__wrapped__.__await__()
else:
return (yield from self.__wrapped__)


def __aenter__(self):
return self.__wrapped__.__aenter__()

async def __aexit__(self, *args, **kwargs):
return await self.__wrapped__.__aexit__(*args, **kwargs)
def __aexit__(self, *args, **kwargs):
return self.__wrapped__.__aexit__(*args, **kwargs)
67 changes: 67 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import pytest

@pytest.fixture(scope="session")
def lop_loader():
def load_implementation(name):
class FakeModule:
subclass = False
kind = name
if name == "slots":
from lazy_object_proxy.slots import Proxy
elif name == "simple":
from lazy_object_proxy.simple import Proxy
elif name == "cext":
try:
from lazy_object_proxy.cext import Proxy
except ImportError:
if PYPY:
pytest.skip(msg="C Extension not available.")
else:
raise
elif name == "objproxies":
Proxy = pytest.importorskip("objproxies").LazyProxy
elif name == "django":
Proxy = pytest.importorskip("django.utils.functional").SimpleLazyObject
else:
raise RuntimeError("Unsupported param: %r." % name)

Proxy

return FakeModule
return load_implementation

@pytest.fixture(scope="session", params=[
"slots", "cext",
"simple",
# "external-django", "external-objproxies"
])
def lop_implementation(request, lop_loader):
return lop_loader(request.param)


@pytest.fixture(scope="session", params=[True, False], ids=['subclassed', 'normal'])
def lop_subclass(request, lop_implementation):
if request.param:
class submod(lop_implementation):
subclass = True
Proxy = type("SubclassOf_" + lop_implementation.Proxy.__name__,
(lop_implementation.Proxy,), {})

return submod
else:
return lop_implementation


@pytest.fixture(scope="function")
def lop(request, lop_subclass):
if request.node.get_closest_marker('xfail_subclass'):
request.applymarker(pytest.mark.xfail(
reason="This test can't work because subclassing disables certain "
"features like __doc__ and __module__ proxying."
))
if request.node.get_closest_marker('xfail_simple'):
request.applymarker(pytest.mark.xfail(
reason="The lazy_object_proxy.simple.Proxy has some limitations."
))

return lop_subclass

0 comments on commit c4ed607

Please sign in to comment.