Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ environment:
PYTHON_HOME: C:\Python27-x64
PYTHON_VERSION: '2.7'
PYTHON_ARCH: '64'
WINDOWS_SDK_VERSION: v7.0
- TOXENV: py27-nocov
TOXPYTHON: C:\Python27\python.exe
PYTHON_HOME: C:\Python27
Expand All @@ -35,7 +34,6 @@ environment:
PYTHON_VERSION: '2.7'
PYTHON_ARCH: '64'
WHEEL_PATH: .tox/dist
WINDOWS_SDK_VERSION: v7.0
- TOXENV: py36-cover,codecov,coveralls
TOXPYTHON: C:\Python36\python.exe
PYTHON_HOME: C:\Python36
Expand Down Expand Up @@ -130,12 +128,9 @@ init:
install:
- '%PYTHON_HOME%\python -mpip install --progress-bar=off -rci/requirements.txt'
- '%PYTHON_HOME%\Scripts\virtualenv --version'
- '%PYTHON_HOME%\Scripts\easy_install --version'
- '%PYTHON_HOME%\Scripts\pip --version'
- '%PYTHON_HOME%\Scripts\tox --version'
test_script:
- cmd /E:ON /V:ON /C .\ci\appveyor-with-compiler.cmd %PYTHON_HOME%\Scripts\tox
on_success:
- ps: |
Set-PSDebug -Trace 1
$ErrorActionPreference = "Stop"
Expand Down
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,10 @@ before_install:
export PATH="/usr/local/opt/python/libexec/bin:${PATH}"
fi
install:
- python -mpip uninstall virtualenv --yes
- python -mpip uninstall virtualenv --yes
- python -mpip install --progress-bar=off --upgrade --ignore-installed -rci/requirements.txt
- virtualenv --version
- easy_install --version
- pip --version
- tox --version
script:
Expand Down
21 changes: 5 additions & 16 deletions ci/appveyor-with-compiler.cmd
Original file line number Diff line number Diff line change
@@ -1,22 +1,11 @@
:: Very simple setup:
:: - if WINDOWS_SDK_VERSION is set then activate the SDK.
:: - disable the WDK if it's around.

SET COMMAND_TO_RUN=%*
SET WIN_SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows
SET WIN_WDK="c:\Program Files (x86)\Windows Kits\10\Include\wdf"
ECHO SDK: %WINDOWS_SDK_VERSION% ARCH: %PYTHON_ARCH%

IF EXIST %WIN_WDK% (
REM See: https://connect.microsoft.com/VisualStudio/feedback/details/1610302/
REN %WIN_WDK% 0wdf
)
IF "%WINDOWS_SDK_VERSION%"=="" GOTO main
IF "%PYTHON_VERSION%"=="2.7" GOTO legacy
GOTO main

SET DISTUTILS_USE_SDK=1
SET MSSdk=1
"%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Setup\WindowsSdkVer.exe" -q -version:%WINDOWS_SDK_VERSION%
CALL "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Bin\SetEnv.cmd" /x64 /release
:legacy
powershell -Command "Invoke-WebRequest https://download.microsoft.com/download/7/9/6/796EF2E4-801B-4FC4-AB28-B59FBF6D907B/VCForPython27.msi -OutFile VCForPython27.msi"
msiexec /i VCForPython27.msi /quiet /qn /norestart

:main
ECHO Executing: %COMMAND_TO_RUN%
Expand Down
6 changes: 0 additions & 6 deletions ci/templates/.appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,16 @@ environment:
{% if 'nocov' in env %}
WHEEL_PATH: .tox/dist
{% endif %}
{% if env.startswith('py2') %}
WINDOWS_SDK_VERSION: v7.0
{% endif %}
{% endif %}{% endfor %}
init:
- ps: echo $env:TOXENV
- ps: ls C:\Python*
install:
- '%PYTHON_HOME%\python -mpip install --progress-bar=off -rci/requirements.txt'
- '%PYTHON_HOME%\Scripts\virtualenv --version'
- '%PYTHON_HOME%\Scripts\easy_install --version'
- '%PYTHON_HOME%\Scripts\pip --version'
- '%PYTHON_HOME%\Scripts\tox --version'
test_script:
- cmd /E:ON /V:ON /C .\ci\appveyor-with-compiler.cmd %PYTHON_HOME%\Scripts\tox
on_success:
- ps: |
Set-PSDebug -Trace 1
$ErrorActionPreference = "Stop"
Expand Down
3 changes: 2 additions & 1 deletion ci/templates/.travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,10 @@ before_install:
export PATH="/usr/local/opt/python/libexec/bin:${PATH}"
fi
install:
- python -mpip uninstall virtualenv --yes
- python -mpip uninstall virtualenv --yes
- python -mpip install --progress-bar=off --upgrade --ignore-installed -rci/requirements.txt
- virtualenv --version
- easy_install --version
- pip --version
- tox --version
script:
Expand Down
10 changes: 10 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import sys

PY3 = sys.version_info[0] >= 3


def pytest_ignore_collect(path, config):
basename = path.basename

if not PY3 and "py3" in basename or PY3 and "py2" in basename:
return True
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@
requires = [
"setuptools>=30.3.0",
"wheel",
"setuptools_scm>=3.3.1",
"setuptools_scm>=3.3.1,<6.0",
]
4 changes: 2 additions & 2 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[options]
setup_requires =
setuptools_scm>=3.3.1
setuptools_scm>=3.3.1,<6.0

[flake8]
max-line-length = 140
Expand Down 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
142 changes: 133 additions & 9 deletions src/lazy_object_proxy/cext.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ PyTypeObject Proxy_Type;
/* ------------------------------------------------------------------------- */

static PyObject *identity_ref = NULL;
static PyObject *await_ref = NULL;
static PyObject *
identity(PyObject *self, PyObject *value)
{
Expand Down Expand Up @@ -457,8 +458,7 @@ static PyObject *Proxy_oct(ProxyObject *self)

if ((nb = self->wrapped->ob_type->tp_as_number) == NULL ||
nb->nb_oct == NULL) {
PyErr_SetString(PyExc_TypeError,
"oct() argument can't be converted to oct");
PyErr_SetString(PyExc_TypeError, "oct() argument can't be converted to oct");
return NULL;
}

Expand All @@ -477,8 +477,7 @@ static PyObject *Proxy_hex(ProxyObject *self)

if ((nb = self->wrapped->ob_type->tp_as_number) == NULL ||
nb->nb_hex == NULL) {
PyErr_SetString(PyExc_TypeError,
"hex() argument can't be converted to hex");
PyErr_SetString(PyExc_TypeError, "hex() argument can't be converted to hex");
return NULL;
}

Expand Down Expand Up @@ -854,8 +853,7 @@ static PyObject *Proxy_dir(

/* ------------------------------------------------------------------------- */

static PyObject *Proxy_enter(
ProxyObject *self, PyObject *args, PyObject *kwds)
static PyObject *Proxy_enter(ProxyObject *self)
{
PyObject *method = NULL;
PyObject *result = NULL;
Expand All @@ -867,7 +865,7 @@ static PyObject *Proxy_enter(
if (!method)
return NULL;

result = PyObject_Call(method, args, kwds);
result = PyObject_CallObject(method, NULL);

Py_DECREF(method);

Expand Down Expand Up @@ -1227,6 +1225,107 @@ static PyObject *Proxy_call(

/* ------------------------------------------------------------------------- */;

#if PY_MAJOR_VERSION >= 3

static PyObject *Proxy_aenter(ProxyObject *self)
{
PyObject *method = NULL;
PyObject *result = NULL;

Proxy__ENSURE_WRAPPED_OR_RETURN_NULL(self);

method = PyObject_GetAttrString(self->wrapped, "__aenter__");

if (!method)
return NULL;

result = PyObject_CallObject(method, NULL);

Py_DECREF(method);

return result;
}

/* ------------------------------------------------------------------------- */

static PyObject *Proxy_aexit(
ProxyObject *self, PyObject *args, PyObject *kwds)
{
PyObject *method = NULL;
PyObject *result = NULL;

Proxy__ENSURE_WRAPPED_OR_RETURN_NULL(self);

method = PyObject_GetAttrString(self->wrapped, "__aexit__");

if (!method)
return NULL;

result = PyObject_Call(method, args, kwds);

Py_DECREF(method);

return result;
}

/* ------------------------------------------------------------------------- */

static PyObject *Proxy_await(ProxyObject *self)
{
Proxy__ENSURE_WRAPPED_OR_RETURN_NULL(self);

return PyObject_CallFunctionObjArgs(await_ref, self->wrapped, NULL);
}

/* ------------------------------------------------------------------------- */;

static PyObject *Proxy_aiter(ProxyObject *self)
{
Proxy__ENSURE_WRAPPED_OR_RETURN_NULL(self);

unaryfunc meth = NULL;
PyObject *wrapped = self->wrapped;
PyTypeObject *type = Py_TYPE(wrapped);

if (type->tp_as_async != NULL) {
meth = type->tp_as_async->am_aiter;
}

if (meth != NULL) {
return (*meth)(wrapped);
}

PyErr_Format(PyExc_AttributeError, "'%.100s' object has no attribute '__aiter__'", type->tp_name);
return NULL;
}

/* ------------------------------------------------------------------------- */;

static PyObject *Proxy_anext(ProxyObject *self)
{
Proxy__ENSURE_WRAPPED_OR_RETURN_NULL(self);


unaryfunc meth = NULL;
PyObject *wrapped = self->wrapped;
PyTypeObject *type = Py_TYPE(wrapped);

if (type->tp_as_async != NULL) {
meth = type->tp_as_async->am_anext;
}

if (meth != NULL) {
return (*meth)(wrapped);
}

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

#endif

/* ------------------------------------------------------------------------- */;

static PyNumberMethods Proxy_as_number = {
(binaryfunc)Proxy_add, /*nb_add*/
(binaryfunc)Proxy_subtract, /*nb_subtract*/
Expand Down Expand Up @@ -1299,10 +1398,17 @@ static PyMappingMethods Proxy_as_mapping = {
(objobjargproc)Proxy_setitem, /*mp_ass_subscript*/
};

#if PY_MAJOR_VERSION >= 3
static PyAsyncMethods Proxy_as_async = {
(unaryfunc)Proxy_await, /* am_await */
(unaryfunc)Proxy_aiter, /* am_aiter */
(unaryfunc)Proxy_anext, /* am_anext */
};
#endif

static PyMethodDef Proxy_methods[] = {
{ "__dir__", (PyCFunction)Proxy_dir, METH_NOARGS, 0 },
{ "__enter__", (PyCFunction)Proxy_enter,
METH_VARARGS | METH_KEYWORDS, 0 },
{ "__enter__", (PyCFunction)Proxy_enter, METH_NOARGS, 0 },
{ "__exit__", (PyCFunction)Proxy_exit,
METH_VARARGS | METH_KEYWORDS, 0 },
{ "__getattr__", (PyCFunction)Proxy_getattr,
Expand All @@ -1314,6 +1420,9 @@ static PyMethodDef Proxy_methods[] = {
{ "__fspath__", (PyCFunction)Proxy_fspath, METH_NOARGS, 0 },
#if PY_MAJOR_VERSION >= 3
{ "__round__", (PyCFunction)Proxy_round, METH_NOARGS, 0 },
{ "__aenter__", (PyCFunction)Proxy_aenter, METH_NOARGS, 0 },
{ "__aexit__", (PyCFunction)Proxy_aexit,
METH_VARARGS | METH_KEYWORDS, 0 },
#endif
{ NULL, NULL },
};
Expand Down Expand Up @@ -1348,7 +1457,11 @@ PyTypeObject Proxy_Type = {
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
#if PY_MAJOR_VERSION >= 3
&Proxy_as_async, /* tp_as_async */
#else
0, /*tp_compare*/
#endif
(unaryfunc)Proxy_repr, /*tp_repr*/
&Proxy_as_number, /*tp_as_number*/
&Proxy_as_sequence, /*tp_as_sequence*/
Expand Down Expand Up @@ -1430,6 +1543,17 @@ moduleinit(void)
return NULL;
Py_INCREF(identity_ref);

#if PY_MAJOR_VERSION >= 3
PyObject *utils_module = PyImport_ImportModule("lazy_object_proxy.utils");
if (utils_module == NULL)
return NULL;

await_ref = PyObject_GetAttrString(utils_module, "await_");
Py_DECREF(utils_module);
if (await_ref == NULL)
return NULL;
#endif

Py_INCREF(&Proxy_Type);
PyModule_AddObject(module, "Proxy",
(PyObject *)&Proxy_Type);
Expand Down
19 changes: 19 additions & 0 deletions src/lazy_object_proxy/simple.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from .compat import PY3
from .compat import string_types
from .compat import with_metaclass
from .utils import await_
from .utils import cached_property
from .utils import identity

Expand Down Expand Up @@ -256,3 +257,21 @@ def __reduce__(self):

def __reduce_ex__(self, protocol):
return identity, (self.__wrapped__,)

if await_ is not None:
exec("""
def __aiter__(self):
return self.__wrapped__.__aiter__()

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

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

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

def __aexit__(self, *args, **kwargs):
return self.__wrapped__.__aexit__(*args, **kwargs)
""")
Loading