Skip to content

Commit dfb2ee2

Browse files
authored
Make zope a semi-optional test dependency (#685)
1 parent 00c1c2c commit dfb2ee2

File tree

4 files changed

+39
-20
lines changed

4 files changed

+39
-20
lines changed

changelog.d/685.change.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
``zope.interface`` is now a "soft dependency" when running the test suite; if ``zope.interface`` is not installed when running the test suite, the interface-related tests will be automatically skipped.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ multi_line_output=3
3535
use_parentheses=true
3636

3737
known_first_party="attr"
38-
known_third_party=["attr", "hypothesis", "pytest", "setuptools", "six", "zope"]
38+
known_third_party=["attr", "hypothesis", "pytest", "setuptools", "six"]
3939

4040

4141
[tool.towncrier]

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,16 @@
3838
INSTALL_REQUIRES = []
3939
EXTRAS_REQUIRE = {
4040
"docs": ["sphinx", "sphinx-rtd-theme", "zope.interface"],
41-
"tests": [
41+
"tests_no_zope": [
4242
# 5.0 introduced toml; parallel was broken until 5.0.2
4343
"coverage[toml]>=5.0.2",
4444
"hypothesis",
4545
"pympler",
4646
"pytest>=4.3.0", # 4.3.0 dropped last use of `convert`
4747
"six",
48-
"zope.interface",
4948
],
5049
}
50+
EXTRAS_REQUIRE["tests"] = EXTRAS_REQUIRE["tests_no_zope"] + ["zope.interface"]
5151
EXTRAS_REQUIRE["dev"] = (
5252
EXTRAS_REQUIRE["tests"] + EXTRAS_REQUIRE["docs"] + ["pre-commit"]
5353
)

tests/test_validators.py

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import re
88

99
import pytest
10-
import zope.interface
1110

1211
import attr
1312

@@ -29,6 +28,19 @@
2928
from .utils import simple_attr
3029

3130

31+
@pytest.fixture(scope="module")
32+
def zope_interface():
33+
"""Provides ``zope.interface`` if available, skipping the test if not."""
34+
try:
35+
import zope.interface
36+
except ImportError:
37+
raise pytest.skip(
38+
"zope-related tests skipped when zope.interface is not installed"
39+
)
40+
41+
return zope.interface
42+
43+
3244
class TestInstanceOf(object):
3345
"""
3446
Tests for `instance_of`.
@@ -217,16 +229,22 @@ class C(object):
217229
assert C.__attrs_attrs__[0].validator == C.__attrs_attrs__[1].validator
218230

219231

220-
class IFoo(zope.interface.Interface):
221-
"""
222-
An interface.
223-
"""
232+
@pytest.fixture(scope="module")
233+
def ifoo(zope_interface):
234+
"""Provides a test ``zope.interface.Interface`` in ``zope`` tests."""
224235

225-
def f():
236+
class IFoo(zope_interface.Interface):
226237
"""
227-
A function called f.
238+
An interface.
228239
"""
229240

241+
def f():
242+
"""
243+
A function called f.
244+
"""
245+
246+
return IFoo
247+
230248

231249
class TestProvides(object):
232250
"""
@@ -239,46 +257,46 @@ def test_in_all(self):
239257
"""
240258
assert provides.__name__ in validator_module.__all__
241259

242-
def test_success(self):
260+
def test_success(self, zope_interface, ifoo):
243261
"""
244262
Nothing happens if value provides requested interface.
245263
"""
246264

247-
@zope.interface.implementer(IFoo)
265+
@zope_interface.implementer(ifoo)
248266
class C(object):
249267
def f(self):
250268
pass
251269

252-
v = provides(IFoo)
270+
v = provides(ifoo)
253271
v(None, simple_attr("x"), C())
254272

255-
def test_fail(self):
273+
def test_fail(self, ifoo):
256274
"""
257275
Raises `TypeError` if interfaces isn't provided by value.
258276
"""
259277
value = object()
260278
a = simple_attr("x")
261279

262-
v = provides(IFoo)
280+
v = provides(ifoo)
263281
with pytest.raises(TypeError) as e:
264282
v(None, a, value)
265283
assert (
266284
"'x' must provide {interface!r} which {value!r} doesn't.".format(
267-
interface=IFoo, value=value
285+
interface=ifoo, value=value
268286
),
269287
a,
270-
IFoo,
288+
ifoo,
271289
value,
272290
) == e.value.args
273291

274-
def test_repr(self):
292+
def test_repr(self, ifoo):
275293
"""
276294
Returned validator has a useful `__repr__`.
277295
"""
278-
v = provides(IFoo)
296+
v = provides(ifoo)
279297
assert (
280298
"<provides validator for interface {interface!r}>".format(
281-
interface=IFoo
299+
interface=ifoo
282300
)
283301
) == repr(v)
284302

0 commit comments

Comments
 (0)