|
5 | 5 | import _frozen_importlib as _bootstrap
|
6 | 6 |
|
7 | 7 | _IS_SETUP = False
|
| 8 | + |
| 9 | + |
8 | 10 | def setup(*, log=print):
|
9 | 11 | global _IS_SETUP, LOG_FUNC
|
10 | 12 |
|
11 | 13 | if not _IS_SETUP:
|
12 | 14 | import sys
|
| 15 | + |
13 | 16 | sys.meta_path.insert(0, WheelFinder)
|
14 | 17 | _IS_SETUP = True
|
15 | 18 |
|
16 | 19 | if not log:
|
| 20 | + |
17 | 21 | def LOG_FUNC(log):
|
18 | 22 | pass
|
| 23 | + |
19 | 24 | else:
|
20 | 25 | LOG_FUNC = log
|
21 | 26 |
|
| 27 | + |
22 | 28 | async def load_package(*args):
|
23 | 29 | await asyncweb.wait_all(_load_package(pkg) for pkg in args)
|
24 | 30 |
|
| 31 | + |
25 | 32 | _loaded_packages = {}
|
26 | 33 |
|
27 | 34 | LOG_FUNC = print
|
28 | 35 |
|
| 36 | + |
29 | 37 | async def _load_package(pkg):
|
30 | 38 | # TODO: support pkg==X.Y semver specifiers as well as arbitrary URLs
|
31 |
| - info = await browser.fetch(f'https://pypi.org/pypi/{pkg}/json', response_format="json") |
32 |
| - name = info['info']['name'] |
33 |
| - ver = info['info']['version'] |
34 |
| - ver_downloads = info['releases'][ver] |
| 39 | + info = await browser.fetch( |
| 40 | + f"https://pypi.org/pypi/{pkg}/json", response_format="json" |
| 41 | + ) |
| 42 | + name = info["info"]["name"] |
| 43 | + ver = info["info"]["version"] |
| 44 | + ver_downloads = info["releases"][ver] |
35 | 45 | try:
|
36 |
| - dl = next(dl for dl in ver_downloads if dl['packagetype'] == 'bdist_wheel') |
| 46 | + dl = next(dl for dl in ver_downloads if dl["packagetype"] == "bdist_wheel") |
37 | 47 | except StopIteration:
|
38 | 48 | raise ValueError(f"no wheel available for package {Name!r} {ver}")
|
39 | 49 | if name in _loaded_packages:
|
40 | 50 | return
|
41 |
| - fname = dl['filename'] |
| 51 | + fname = dl["filename"] |
42 | 52 | LOG_FUNC(f"Downloading {fname} ({format_size(dl['size'])})...")
|
43 |
| - zip_data = io.BytesIO(await browser.fetch(dl['url'], response_format="array_buffer")) |
| 53 | + zip_data = io.BytesIO( |
| 54 | + await browser.fetch(dl["url"], response_format="array_buffer") |
| 55 | + ) |
44 | 56 | size = len(zip_data.getbuffer())
|
45 | 57 | LOG_FUNC(f"{fname} done!")
|
46 | 58 | _loaded_packages[name] = zipfile.ZipFile(zip_data)
|
47 | 59 |
|
| 60 | + |
48 | 61 | def format_size(bytes):
|
49 | 62 | # type: (float) -> str
|
50 | 63 | if bytes > 1000 * 1000:
|
51 |
| - return '{:.1f} MB'.format(bytes / 1000.0 / 1000) |
| 64 | + return "{:.1f} MB".format(bytes / 1000.0 / 1000) |
52 | 65 | elif bytes > 10 * 1000:
|
53 |
| - return '{} kB'.format(int(bytes / 1000)) |
| 66 | + return "{} kB".format(int(bytes / 1000)) |
54 | 67 | elif bytes > 1000:
|
55 |
| - return '{:.1f} kB'.format(bytes / 1000.0) |
| 68 | + return "{:.1f} kB".format(bytes / 1000.0) |
56 | 69 | else:
|
57 |
| - return '{} bytes'.format(int(bytes)) |
| 70 | + return "{} bytes".format(int(bytes)) |
| 71 | + |
58 | 72 |
|
59 | 73 | class WheelFinder:
|
60 | 74 | _packages = _loaded_packages
|
61 |
| - |
| 75 | + |
62 | 76 | @classmethod
|
63 | 77 | def find_spec(cls, fullname, path=None, target=None):
|
64 |
| - path = fullname.replace('.', '/') |
| 78 | + path = fullname.replace(".", "/") |
65 | 79 | for zname, z in cls._packages.items():
|
66 | 80 | mi, fullpath = _get_module_info(z, path)
|
67 | 81 | if mi is not None:
|
68 |
| - return _bootstrap.spec_from_loader(fullname, cls, origin=f'wheel:{zname}/{fullpath}', is_package=mi) |
| 82 | + return _bootstrap.spec_from_loader( |
| 83 | + fullname, cls, origin=f"wheel:{zname}/{fullpath}", is_package=mi |
| 84 | + ) |
69 | 85 | return None
|
70 |
| - |
| 86 | + |
71 | 87 | @classmethod
|
72 | 88 | def create_module(cls, spec):
|
73 | 89 | return None
|
74 |
| - |
| 90 | + |
75 | 91 | @classmethod
|
76 | 92 | def get_source(cls, fullname):
|
77 | 93 | spec = cls.find_spec(fullname)
|
78 | 94 | if spec:
|
79 | 95 | return cls._get_source(spec)
|
80 | 96 | else:
|
81 |
| - raise ImportError('cannot find source for module', name=fullname) |
| 97 | + raise ImportError("cannot find source for module", name=fullname) |
82 | 98 |
|
83 | 99 | @classmethod
|
84 | 100 | def _get_source(cls, spec):
|
85 | 101 | origin = spec.origin
|
86 | 102 | if not origin or not origin.startswith("wheel:"):
|
87 |
| - raise ImportError(f'{module.__spec__.name!r} is not a zip module') |
| 103 | + raise ImportError(f"{module.__spec__.name!r} is not a zip module") |
88 | 104 |
|
89 |
| - zipname, slash, path = origin[len('wheel:'):].partition('/') |
| 105 | + zipname, slash, path = origin[len("wheel:") :].partition("/") |
90 | 106 | return cls._packages[zipname].read(path).decode()
|
91 | 107 |
|
92 | 108 | @classmethod
|
93 | 109 | def exec_module(cls, module):
|
94 | 110 | spec = module.__spec__
|
95 | 111 | source = cls._get_source(spec)
|
96 |
| - code = _bootstrap._call_with_frames_removed(compile, source, spec.origin, 'exec', dont_inherit=True) |
| 112 | + code = _bootstrap._call_with_frames_removed( |
| 113 | + compile, source, spec.origin, "exec", dont_inherit=True |
| 114 | + ) |
97 | 115 | _bootstrap._call_with_frames_removed(exec, code, module.__dict__)
|
98 | 116 |
|
99 | 117 |
|
100 | 118 | _zip_searchorder = (
|
101 | 119 | # (path_sep + '__init__.pyc', True, True),
|
102 |
| - ('/__init__.py', False, True), |
| 120 | + ("/__init__.py", False, True), |
103 | 121 | # ('.pyc', True, False),
|
104 |
| - ('.py', False, False), |
| 122 | + (".py", False, False), |
105 | 123 | )
|
106 | 124 |
|
| 125 | + |
107 | 126 | def _get_module_info(zf, path):
|
108 | 127 | for suffix, isbytecode, ispackage in _zip_searchorder:
|
109 | 128 | fullpath = path + suffix
|
|
0 commit comments