Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/importlib_resources/future/adapters.py: 64%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

42 statements  

1import functools 

2import pathlib 

3from contextlib import suppress 

4from types import SimpleNamespace 

5 

6from .. import readers, _adapters 

7 

8 

9def _block_standard(reader_getter): 

10 """ 

11 Wrap _adapters.TraversableResourcesLoader.get_resource_reader 

12 and intercept any standard library readers. 

13 """ 

14 

15 @functools.wraps(reader_getter) 

16 def wrapper(*args, **kwargs): 

17 """ 

18 If the reader is from the standard library, return None to allow 

19 allow likely newer implementations in this library to take precedence. 

20 """ 

21 try: 

22 reader = reader_getter(*args, **kwargs) 

23 except NotADirectoryError: 

24 # MultiplexedPath may fail on zip subdirectory 

25 return 

26 # Python 3.10+ 

27 mod_name = reader.__class__.__module__ 

28 if mod_name.startswith('importlib.') and mod_name.endswith('readers'): 

29 return 

30 # Python 3.8, 3.9 

31 if isinstance(reader, _adapters.CompatibilityFiles) and ( 

32 reader.spec.loader.__class__.__module__.startswith('zipimport') 

33 or reader.spec.loader.__class__.__module__.startswith( 

34 '_frozen_importlib_external' 

35 ) 

36 ): 

37 return 

38 return reader 

39 

40 return wrapper 

41 

42 

43def _skip_degenerate(reader): 

44 """ 

45 Mask any degenerate reader. Ref #298. 

46 """ 

47 is_degenerate = ( 

48 isinstance(reader, _adapters.CompatibilityFiles) and not reader._reader 

49 ) 

50 return reader if not is_degenerate else None 

51 

52 

53class TraversableResourcesLoader(_adapters.TraversableResourcesLoader): 

54 """ 

55 Adapt loaders to provide TraversableResources and other 

56 compatibility. 

57 

58 Ensures the readers from importlib_resources are preferred 

59 over stdlib readers. 

60 """ 

61 

62 def get_resource_reader(self, name): 

63 return ( 

64 _skip_degenerate(_block_standard(super().get_resource_reader)(name)) 

65 or self._standard_reader() 

66 or super().get_resource_reader(name) 

67 ) 

68 

69 def _standard_reader(self): 

70 return self._zip_reader() or self._namespace_reader() or self._file_reader() 

71 

72 def _zip_reader(self): 

73 with suppress(AttributeError): 

74 return readers.ZipReader(self.spec.loader, self.spec.name) 

75 

76 def _namespace_reader(self): 

77 with suppress(AttributeError, ValueError): 

78 return readers.NamespaceReader(self.spec.submodule_search_locations) 

79 

80 def _file_reader(self): 

81 try: 

82 path = pathlib.Path(self.spec.origin) 

83 except TypeError: 

84 return None 

85 if path.exists(): 

86 return readers.FileReader(SimpleNamespace(path=path)) 

87 

88 

89def wrap_spec(package): 

90 """ 

91 Override _adapters.wrap_spec to use TraversableResourcesLoader 

92 from above. Ensures that future behavior is always available on older 

93 Pythons. 

94 """ 

95 return _adapters.SpecLoaderAdapter(package.__spec__, TraversableResourcesLoader)