1313# limitations under the License.
1414
1515import copy
16+ import pathlib
1617from unittest import TestCase
1718
1819from _pytest ._code .code import ReprFileLocation
2324from ..test_runner import LaunchTestRunner
2425
2526
27+ def _pytest_version_ge (major , minor = 0 , patch = 0 ):
28+ """Return True if pytest version is >= the given version."""
29+ pytest_version = tuple ([int (v ) for v in pytest .__version__ .split ('.' )])
30+ assert pytest_version
31+ return pytest_version >= (major , minor , patch )
32+
33+
2634class LaunchTestFailure (Exception ):
2735
2836 def __init__ (self , message , results ):
@@ -119,29 +127,42 @@ def repr_failure(self, excinfo):
119127 return super ().repr_failure (excinfo )
120128
121129 def reportinfo (self ):
122- return self .fspath , 0 , 'launch tests: {}' .format (self .name )
130+ if _pytest_version_ge (7 ):
131+ path = self .path
132+ else :
133+ path = self .fspath
134+ return path , 0 , 'launch tests: {}' .format (self .name )
123135
124136
125137class LaunchTestModule (pytest .File ):
126138
127- def __init__ (self , parent , * , fspath ):
128- super ().__init__ (parent = parent , fspath = fspath )
139+ def __init__ (self , * args , ** kwargs ):
140+ if _pytest_version_ge (7 ):
141+ if 'fspath' in kwargs :
142+ if kwargs ['fspath' ] is not None :
143+ kwargs ['path' ] = pathlib .Path (kwargs ['fspath' ])
144+ del kwargs ['fspath' ]
145+ super ().__init__ (* args , ** kwargs )
129146
130147 @classmethod
131- def from_parent (cls , parent , * , fspath ):
148+ def from_parent (cls , * args , ** kwargs ):
132149 """Override from_parent for compatibility."""
133150 # pytest.File.from_parent didn't exist before pytest 5.4
134- if hasattr (super (), 'from_parent' ):
135- instance = getattr (super (), 'from_parent' )(parent = parent , fspath = fspath )
136- else :
137- instance = cls (parent = parent , fspath = fspath )
138- return instance
151+ if _pytest_version_ge (5 , 4 ):
152+ return super ().from_parent (* args , ** kwargs )
153+ args_without_parent = args [1 :]
154+ return cls (* args_without_parent , ** kwargs )
139155
140156 def makeitem (self , * args , ** kwargs ):
141157 return LaunchTestItem .from_parent (* args , ** kwargs )
142158
143159 def collect (self ):
144- module = self .fspath .pyimport ()
160+ if _pytest_version_ge (7 ):
161+ # self.path exists since 7
162+ from _pytest .pathlib import import_path
163+ module = import_path (self .path , root = None )
164+ else :
165+ module = self .fspath .pyimport ()
145166 yield self .makeitem (
146167 name = module .__name__ , parent = self ,
147168 test_runs = LoadTestsFromPythonModule (
@@ -152,7 +173,13 @@ def collect(self):
152173
153174def find_launch_test_entrypoint (path ):
154175 try :
155- return getattr (path .pyimport (), 'generate_test_description' , None )
176+ if _pytest_version_ge (7 ):
177+ from _pytest .pathlib import import_path
178+ module = import_path (path , root = None )
179+ else :
180+ # Assume we got legacy path in earlier versions of pytest
181+ module = path .pyimport ()
182+ return getattr (module , 'generate_test_description' , None )
156183 except SyntaxError :
157184 return None
158185
@@ -166,26 +193,32 @@ def pytest_pycollect_makemodule(path, parent):
166193 )
167194 if module is not None :
168195 return module
169- if path .basename == '__init__.py' :
170- try :
171- # since https://docs.pytest.org/en/latest/changelog.html#deprecations
172- # todo: remove fallback once all platforms use pytest >=5.4
196+
197+ if _pytest_version_ge (7 ):
198+ path = pathlib .Path (path )
199+ if path .name == '__init__.py' :
200+ return pytest .Package .from_parent (parent , path = path )
201+ return pytest .Module .from_parent (parent = parent , path = path )
202+ elif _pytest_version_ge (5 , 4 ):
203+ if path .basename == '__init__.py' :
173204 return pytest .Package .from_parent (parent , fspath = path )
174- except AttributeError :
175- return pytest .Package (path , parent )
176- try :
177- # since https://docs.pytest.org/en/latest/changelog.html#deprecations
178- # todo: remove fallback once all platforms use pytest >=5.4
179205 return pytest .Module .from_parent (parent , fspath = path )
180- except AttributeError :
206+ else :
207+ # todo: remove fallback once all platforms use pytest >=5.4
208+ if path .basename == '__init__.py' :
209+ return pytest .Package (path , parent )
181210 return pytest .Module (path , parent )
182211
183212
184213@pytest .hookimpl (trylast = True )
185214def pytest_launch_collect_makemodule (path , parent , entrypoint ):
186215 marks = getattr (entrypoint , 'pytestmark' , [])
187216 if marks and any (m .name == 'launch_test' for m in marks ):
188- return LaunchTestModule .from_parent (parent , fspath = path )
217+ if _pytest_version_ge (7 ):
218+ path = pathlib .Path (path )
219+ return LaunchTestModule .from_parent (parent = parent , path = path )
220+ else :
221+ return LaunchTestModule .from_parent (parent = parent , fspath = path )
189222
190223
191224def pytest_addhooks (pluginmanager ):
0 commit comments