File importlib-metadata.patch of Package python-pytest (Revision f213a27bb0b551d0feba19a4a1390029)
Currently displaying revision f213a27bb0b551d0feba19a4a1390029 , Show latest
xxxxxxxxxx
1
From 13f02af97d676bdf7143aa1834c8898fbf753d87 Mon Sep 17 00:00:00 2001
2
From: Anthony Sottile <asottile@umich.edu>
3
Date: Sat, 6 Apr 2019 17:32:47 -0700
4
Subject: [PATCH] Switch to importlib-metadata
5
6
---
7
changelog/5063.feature.rst | 1 +
8
setup.py | 5 +-
9
src/_pytest/assertion/rewrite.py | 19 -----
10
src/_pytest/config/__init__.py | 21 ++----
11
src/_pytest/outcomes.py | 12 +--
12
testing/acceptance_test.py | 31 +++-----
13
testing/test_assertion.py | 56 +++++---------
14
testing/test_config.py | 121 ++++++++++++-------------------
15
testing/test_entry_points.py | 14 +---
16
9 files changed, 95 insertions(+), 185 deletions(-)
17
create mode 100644 changelog/5063.feature.rst
18
19
Index: pytest-3.10.1/setup.py
20
===================================================================
21
--- pytest-3.10.1.orig/setup.py
22
+++ pytest-3.10.1/setup.py
23
24
INSTALL_REQUIRES = [
25
"py>=1.5.0",
26
"six>=1.10.0",
27
- "setuptools",
28
+ "packaging",
29
"attrs>=17.4.0",
30
"more-itertools>=4.0.0",
31
"atomicwrites>=1.0",
32
'funcsigs;python_version<"3.0"',
33
'pathlib2>=2.2.0;python_version<"3.6"',
34
'colorama;sys_platform=="win32"',
35
+ 'importlib-metadata>=0.12',
36
]
37
38
39
# if _PYTEST_SETUP_SKIP_PLUGGY_DEP is set, skip installing pluggy;
40
# used by tox.ini to test with pluggy master
41
if "_PYTEST_SETUP_SKIP_PLUGGY_DEP" not in os.environ:
42
- INSTALL_REQUIRES.append("pluggy>=0.7")
43
+ INSTALL_REQUIRES.append("pluggy>=0.12")
44
45
46
def main():
47
Index: pytest-3.10.1/src/_pytest/assertion/rewrite.py
48
===================================================================
49
--- pytest-3.10.1.orig/src/_pytest/assertion/rewrite.py
50
+++ pytest-3.10.1/src/_pytest/assertion/rewrite.py
51
52
self.session = None
53
self.modules = {}
54
self._rewritten_names = set()
55
- self._register_with_pkg_resources()
56
self._must_rewrite = set()
57
# flag to guard against trying to rewrite a pyc file while we are already writing another pyc file,
58
# which might result in infinite recursion (#3506)
59
60
tp = desc[2]
61
return tp == imp.PKG_DIRECTORY
62
63
- @classmethod
64
- def _register_with_pkg_resources(cls):
65
- """
66
- Ensure package resources can be loaded from this loader. May be called
67
- multiple times, as the operation is idempotent.
68
- """
69
- try:
70
- import pkg_resources
71
-
72
- # access an attribute in case a deferred importer is present
73
- pkg_resources.__name__
74
- except ImportError:
75
- return
76
-
77
- # Since pytest tests are always located in the file system, the
78
- # DefaultProvider is appropriate.
79
- pkg_resources.register_loader_type(cls, pkg_resources.DefaultProvider)
80
-
81
def get_data(self, pathname):
82
"""Optional PEP302 get_data API.
83
"""
84
Index: pytest-3.10.1/src/_pytest/config/__init__.py
85
===================================================================
86
--- pytest-3.10.1.orig/src/_pytest/config/__init__.py
87
+++ pytest-3.10.1/src/_pytest/config/__init__.py
88
89
import sys
90
import types
91
import warnings
92
-from distutils.version import LooseVersion
93
94
+import importlib_metadata
95
import py
96
import six
97
+from packaging.version import Version
98
from pluggy import HookimplMarker
99
from pluggy import HookspecMarker
100
from pluggy import PluginManager
101
102
modules or packages in the distribution package for
103
all pytest plugins.
104
"""
105
- import pkg_resources
106
-
107
self.pluginmanager.rewrite_hook = hook
108
109
if os.environ.get("PYTEST_DISABLE_PLUGIN_AUTOLOAD"):
110
# We don't autoload from setuptools entry points, no need to continue.
111
return
112
113
- # 'RECORD' available for plugins installed normally (pip install)
114
- # 'SOURCES.txt' available for plugins installed in dev mode (pip install -e)
115
- # for installed plugins 'SOURCES.txt' returns an empty list, and vice-versa
116
- # so it shouldn't be an issue
117
- metadata_files = "RECORD", "SOURCES.txt"
118
-
119
package_files = (
120
- entry.split(",")[0]
121
- for entrypoint in pkg_resources.iter_entry_points("pytest11")
122
- for metadata in metadata_files
123
- for entry in entrypoint.dist._get_metadata(metadata)
124
+ str(file)
125
+ for dist in importlib_metadata.distributions()
126
+ if any(ep.group == "pytest11" for ep in dist.entry_points)
127
+ for file in dist.files
128
)
129
130
for name in _iter_rewritable_modules(package_files):
131
132
133
minver = self.inicfg.get("minversion", None)
134
if minver:
135
- if LooseVersion(minver) > LooseVersion(pytest.__version__):
136
+ if Version(minver) > Version(pytest.__version__):
137
raise pytest.UsageError(
138
"%s:%d: requires pytest-%s, actual pytest-%s'"
139
% (
140
Index: pytest-3.10.1/src/_pytest/outcomes.py
141
===================================================================
142
--- pytest-3.10.1.orig/src/_pytest/outcomes.py
143
+++ pytest-3.10.1/src/_pytest/outcomes.py
144
145
146
import sys
147
148
+from packaging.version import Version
149
+
150
151
class OutcomeException(BaseException):
152
""" OutcomeException and its subclass instances indicate and
153
154
return mod
155
verattr = getattr(mod, "__version__", None)
156
if minversion is not None:
157
- try:
158
- from pkg_resources import parse_version as pv
159
- except ImportError:
160
- raise Skipped(
161
- "we have a required version for %r but can not import "
162
- "pkg_resources to parse version strings." % (modname,),
163
- allow_module_level=True,
164
- )
165
- if verattr is None or pv(verattr) < pv(minversion):
166
+ if verattr is None or Version(verattr) < Version(minversion):
167
raise Skipped(
168
"module %r has __version__ %r, required is: %r"
169
% (modname, verattr, minversion),
170
Index: pytest-3.10.1/testing/test_assertion.py
171
===================================================================
172
--- pytest-3.10.1.orig/testing/test_assertion.py
173
+++ pytest-3.10.1/testing/test_assertion.py
174
175
def test_pytest_plugins_rewrite_module_names_correctly(self, testdir):
176
"""Test that we match files correctly when they are marked for rewriting (#2939)."""
177
contents = {
178
- "conftest.py": """
179
+ "conftest.py": """\
180
pytest_plugins = "ham"
181
""",
182
"ham.py": "",
183
"hamster.py": "",
184
- "test_foo.py": """
185
+ "test_foo.py": """\
186
def test_foo(pytestconfig):
187
assert pytestconfig.pluginmanager.rewrite_hook.find_module('ham') is not None
188
assert pytestconfig.pluginmanager.rewrite_hook.find_module('hamster') is None
189
190
assert result.ret == 0
191
192
@pytest.mark.parametrize("mode", ["plain", "rewrite"])
193
- @pytest.mark.parametrize("plugin_state", ["development", "installed"])
194
- def test_installed_plugin_rewrite(self, testdir, mode, plugin_state):
195
+ def test_installed_plugin_rewrite(self, testdir, mode, monkeypatch):
196
+ monkeypatch.delenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", raising=False)
197
# Make sure the hook is installed early enough so that plugins
198
# installed via setuptools are rewritten.
199
testdir.tmpdir.join("hampkg").ensure(dir=1)
200
contents = {
201
- "hampkg/__init__.py": """
202
+ "hampkg/__init__.py": """\
203
import pytest
204
205
@pytest.fixture
206
207
assert values.pop(0) == value
208
return check
209
""",
210
- "spamplugin.py": """
211
+ "spamplugin.py": """\
212
import pytest
213
from hampkg import check_first2
214
215
216
assert values.pop(0) == value
217
return check
218
""",
219
- "mainwrapper.py": """
220
- import pytest, pkg_resources
221
-
222
- plugin_state = "{plugin_state}"
223
-
224
- class DummyDistInfo(object):
225
- project_name = 'spam'
226
- version = '1.0'
227
-
228
- def _get_metadata(self, name):
229
- # 'RECORD' meta-data only available in installed plugins
230
- if name == 'RECORD' and plugin_state == "installed":
231
- return ['spamplugin.py,sha256=abc,123',
232
- 'hampkg/__init__.py,sha256=abc,123']
233
- # 'SOURCES.txt' meta-data only available for plugins in development mode
234
- elif name == 'SOURCES.txt' and plugin_state == "development":
235
- return ['spamplugin.py',
236
- 'hampkg/__init__.py']
237
- return []
238
+ "mainwrapper.py": """\
239
+ import pytest, importlib_metadata
240
241
class DummyEntryPoint(object):
242
name = 'spam'
243
module_name = 'spam.py'
244
- attrs = ()
245
- extras = None
246
- dist = DummyDistInfo()
247
+ group = 'pytest11'
248
249
- def load(self, require=True, *args, **kwargs):
250
+ def load(self):
251
import spamplugin
252
return spamplugin
253
254
- def iter_entry_points(group, name=None):
255
- yield DummyEntryPoint()
256
+ class DummyDistInfo(object):
257
+ version = '1.0'
258
+ files = ('spamplugin.py', 'hampkg/__init__.py')
259
+ entry_points = (DummyEntryPoint(),)
260
+ metadata = {'name': 'foo'}
261
262
- pkg_resources.iter_entry_points = iter_entry_points
263
+ def distributions():
264
+ return (DummyDistInfo(),)
265
+
266
+ importlib_metadata.distributions = distributions
267
pytest.main()
268
- """.format(
269
- plugin_state=plugin_state
270
- ),
271
- "test_foo.py": """
272
+ """,
273
+ "test_foo.py": """\
274
def test(check_first):
275
check_first([10, 30], 30)
276
277
Index: pytest-3.10.1/testing/test_config.py
278
===================================================================
279
--- pytest-3.10.1.orig/testing/test_config.py
280
+++ pytest-3.10.1/testing/test_config.py
281
282
import sys
283
import textwrap
284
285
+import importlib_metadata
286
+
287
import _pytest._code
288
import pytest
289
from _pytest.config import _iter_rewritable_modules
290
291
292
293
def test_preparse_ordering_with_setuptools(testdir, monkeypatch):
294
- pkg_resources = pytest.importorskip("pkg_resources")
295
-
296
- def my_iter(group, name=None):
297
- assert group == "pytest11"
298
299
- class Dist(object):
300
- project_name = "spam"
301
- version = "1.0"
302
+ class EntryPoint(object):
303
+ name = "mytestplugin"
304
+ group = "pytest11"
305
306
- def _get_metadata(self, name):
307
- return ["foo.txt,sha256=abc,123"]
308
+ def load(self):
309
+ class PseudoPlugin(object):
310
+ x = 42
311
312
- class EntryPoint(object):
313
- name = "mytestplugin"
314
- dist = Dist()
315
+ return PseudoPlugin()
316
317
- def load(self):
318
- class PseudoPlugin(object):
319
- x = 42
320
+ class Dist(object):
321
+ files = ()
322
+ entry_points = (EntryPoint(),)
323
324
- return PseudoPlugin()
325
+ def my_dists():
326
+ return (Dist,)
327
328
- return iter([EntryPoint()])
329
-
330
- monkeypatch.setattr(pkg_resources, "iter_entry_points", my_iter)
331
+ monkeypatch.setattr(importlib_metadata, "distributions", my_dists)
332
testdir.makeconftest(
333
"""
334
pytest_plugins = "mytestplugin",
335
336
337
338
def test_setuptools_importerror_issue1479(testdir, monkeypatch):
339
- pkg_resources = pytest.importorskip("pkg_resources")
340
-
341
- def my_iter(group, name=None):
342
- assert group == "pytest11"
343
-
344
- class Dist(object):
345
- project_name = "spam"
346
- version = "1.0"
347
-
348
- def _get_metadata(self, name):
349
- return ["foo.txt,sha256=abc,123"]
350
-
351
- class EntryPoint(object):
352
- name = "mytestplugin"
353
- dist = Dist()
354
-
355
- def load(self):
356
- raise ImportError("Don't hide me!")
357
+ class DummyEntryPoint(object):
358
+ name = "mytestplugin"
359
+ group = "pytest11"
360
+ def load(self):
361
+ raise ImportError("Don't hide me!")
362
+
363
+ class Distribution(object):
364
+ version = "1.0"
365
+ files = ("foo.txt",)
366
+ entry_points = (DummyEntryPoint(),)
367
368
- return iter([EntryPoint()])
369
+ def distributions():
370
+ return (Distribution(),)
371
372
- monkeypatch.setattr(pkg_resources, "iter_entry_points", my_iter)
373
+ monkeypatch.setattr(importlib_metadata, "distributions", distributions)
374
with pytest.raises(ImportError):
375
testdir.parseconfig()
376
377
378
@pytest.mark.parametrize("block_it", [True, False])
379
def test_plugin_preparse_prevents_setuptools_loading(testdir, monkeypatch, block_it):
380
- pkg_resources = pytest.importorskip("pkg_resources")
381
-
382
plugin_module_placeholder = object()
383
384
- def my_iter(group, name=None):
385
- assert group == "pytest11"
386
-
387
- class Dist(object):
388
- project_name = "spam"
389
- version = "1.0"
390
-
391
- def _get_metadata(self, name):
392
- return ["foo.txt,sha256=abc,123"]
393
-
394
- class EntryPoint(object):
395
- name = "mytestplugin"
396
- dist = Dist()
397
+ class DummyEntryPoint(object):
398
+ name = "mytestplugin"
399
+ group = "pytest11"
400
+
401
+ def load(self):
402
+ return plugin_module_placeholder
403
+
404
+ class Distribution(object):
405
+ version = "1.0"
406
+ files = ("foo.txt",)
407
+ entry_points = (DummyEntryPoint(),)
408
409
- def load(self):
410
- return plugin_module_placeholder
411
+ def distributions():
412
+ return (Distribution(),)
413
414
- return iter([EntryPoint()])
415
-
416
- monkeypatch.setattr(pkg_resources, "iter_entry_points", my_iter)
417
+ monkeypatch.setattr(importlib_metadata, "distributions", distributions)
418
args = ("-p", "no:mytestplugin") if block_it else ()
419
config = testdir.parseconfig(*args)
420
config.pluginmanager.import_plugin("mytestplugin")
421
422
"parse_args,should_load", [(("-p", "mytestplugin"), True), ((), False)]
423
)
424
def test_disable_plugin_autoload(testdir, monkeypatch, parse_args, should_load):
425
- pkg_resources = pytest.importorskip("pkg_resources")
426
-
427
- def my_iter(group, name=None):
428
- raise AssertionError("Should not be called")
429
-
430
+ class DummyEntryPoint(object):
431
+ project_name = name = "mytestplugin"
432
+ group = "pytest11"
433
+
434
+ class Distribution(object):
435
+ entry_points = (DummyEntryPoint(),)
436
+ files = ()
437
class PseudoPlugin(object):
438
x = 42
439
440
+ def distributions():
441
+ return (Distribution(),)
442
+
443
monkeypatch.setenv("PYTEST_DISABLE_PLUGIN_AUTOLOAD", "1")
444
- monkeypatch.setattr(pkg_resources, "iter_entry_points", my_iter)
445
+ monkeypatch.setattr(importlib_metadata, "distributions", distributions)
446
monkeypatch.setitem(sys.modules, "mytestplugin", PseudoPlugin())
447
config = testdir.parseconfig(*parse_args)
448
has_loaded = config.pluginmanager.get_plugin("mytestplugin") is not None
449
Index: pytest-3.10.1/testing/test_entry_points.py
450
===================================================================
451
--- pytest-3.10.1.orig/testing/test_entry_points.py
452
+++ pytest-3.10.1/testing/test_entry_points.py
453
454
from __future__ import division
455
from __future__ import print_function
456
457
-import pkg_resources
458
-
459
-import pytest
460
-
461
-
462
-@pytest.mark.parametrize("entrypoint", ["py.test", "pytest"])
463
-def test_entry_point_exist(entrypoint):
464
- assert entrypoint in pkg_resources.get_entry_map("pytest")["console_scripts"]
465
+import importlib_metadata
466
467
468
def test_pytest_entry_points_are_identical():
469
- entryMap = pkg_resources.get_entry_map("pytest")["console_scripts"]
470
- assert entryMap["pytest"].module_name == entryMap["py.test"].module_name
471
+ dist = importlib_metadata.distribution("pytest")
472
+ entry_map = {ep.name: ep for ep in dist.entry_points}
473
+ assert entry_map["pytest"].value == entry_map["py.test"].value
474