33###########################################################################
44import os
55import sys
6+ from importlib .metadata import PackageNotFoundError , metadata
67from pathlib import Path
78
89import pytest
910
1011
12+ def xfail_if_not_installed (package_name ):
13+ """A test decorator that xfails a test if the named package isn't installed.
14+
15+ The third-party tests are dependant on packages being built. During pre-release some
16+ packages won't be compilable. So - the pyproject.toml installs third party packages
17+ with a version conditional gate.
18+
19+ This decorator checks for app metadata (which is an indicator that the package has
20+ been installed). If the metadata exists, the test is executed; if it isn't we XFAIL
21+ the test because it *can't* pass.
22+ """
23+
24+ def _xfail_if_not_installed (fn ):
25+ def _testfunc (* args , ** kwargs ):
26+ try :
27+ metadata (package_name )
28+ except PackageNotFoundError :
29+ pytest .xfail (f"{ package_name } is not installed" )
30+
31+ # Actually run the test
32+ fn (* args , ** kwargs )
33+
34+ return _testfunc
35+
36+ return _xfail_if_not_installed
37+
38+
39+ @xfail_if_not_installed ("pillow" )
1140def test_module_paths ():
1241 "Third party binary modules have meaningful __file__ attributes"
1342 import PIL
@@ -22,6 +51,7 @@ def test_module_paths():
2251
2352
2453@pytest .mark .skipif (sys .platform == "win32" , reason = "cffi not available on windows" )
54+ @xfail_if_not_installed ("cffi" )
2555def test_cffi ():
2656 "CFFI can be used as an alternative FFI interface"
2757 from cffi import FFI
@@ -32,6 +62,7 @@ def test_cffi():
3262 assert lib .strlen (ffi .new ("char[]" , b"hello world" )) == 11
3363
3464
65+ @xfail_if_not_installed ("cryptography" )
3566def test_cryptography ():
3667 "The cryptography module can be used"
3768 # Cryptography is a common binary library that uses cffi and OpenSSL internally
@@ -87,6 +118,7 @@ def test_cryptography():
87118 assert "www.android.com" == domain
88119
89120
121+ @xfail_if_not_installed ("lru-dict" )
90122def test_lru_dict ():
91123 "The LRUDict binary module can be used"
92124 # lru-dict is the simplest possible example of a third-party module.
@@ -107,6 +139,7 @@ def test_lru_dict():
107139 assert lru_dict [f"item_{ i } " ] == i
108140
109141
142+ @xfail_if_not_installed ("pillow" )
110143def test_pillow ():
111144 "Pillow can be used to load images"
112145 # Pillow is a module that has dependencies on other libraries (libjpeg, libft2)
@@ -122,6 +155,7 @@ def test_pillow():
122155 image .close ()
123156
124157
158+ @xfail_if_not_installed ("numpy" )
125159def test_numpy ():
126160 "Numpy Arrays can be created"
127161 from numpy import array
@@ -130,6 +164,7 @@ def test_numpy():
130164 assert [4 , 7 ] == (array ([1 , 2 ]) + array ([3 , 5 ])).tolist ()
131165
132166
167+ @xfail_if_not_installed ("pandas" )
133168def test_pandas ():
134169 "Pandas DataFrames can be created"
135170 from pandas import DataFrame , __version__
0 commit comments