Skip to content

Commit b38d781

Browse files
committed
update the lazy_install mode
1 parent 3a82a78 commit b38d781

File tree

6 files changed

+75
-12
lines changed

6 files changed

+75
-12
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,18 @@ Details:
373373

374374
# Changelogs
375375

376+
- 2021.04.22
377+
- update the lazy_install mode (`-d`)
378+
- simple use case:
379+
- 1. `python -m zipapps -d six`
380+
- 2. `python app.pyz -c "import six;print(six.__file__)"`
381+
- it will not `rmtree` the `_zipapps_lazy_pip` folder for new build
382+
- if you need to upgrade those requirements, use `-U` arg of pip
383+
- lazy_install mode will install requirements with `pip install` while first running
384+
- so you can just run like this to init its installation(`-m` not set): `python3 app.pyz -V`
385+
- for now, `-d` is to server for the cross-platform and cross-python-version app
386+
- pip target path is separated from different python version and system platform
387+
- python version accurity can be reset with `-pva 5`, defaults to 2, means 3.8.3 and 3.8.4 are same `3.8`
376388
- 2021.04.11
377389
- add `--sys-paths` to include new paths of sys.path
378390
- support TEMP/HOME/SELF prefix, separated by commas

test_utils.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,19 @@ def test_create_app_function():
439439
assert b'Installing collected packages' in stdout_output
440440
assert stdout_output.count(b'zipapps_cache') == 2, stdout_output.count(
441441
b'zipapps_cache')
442+
app_path = create_app(lazy_install=True,
443+
pip_args=['bottle', '-r', '_requirements.txt'])
444+
stdout_output, stderr_output = subprocess.Popen(
445+
[
446+
sys.executable,
447+
str(app_path), '-c',
448+
'import six,bottle;print(six.__file__, bottle.__file__)'
449+
],
450+
stderr=subprocess.PIPE,
451+
stdout=subprocess.PIPE,
452+
).communicate()
453+
# print(stdout_output, stderr_output)
454+
assert b'already exists' in stderr_output
442455

443456
# test sys_path
444457
_clean_paths()

zipapps/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
from .main import create_app
33
from .activate_zipapps import activate
44
__all__ = ['create_app', 'activate']
5-
__version__ = '2021.04.11'
5+
__version__ = '2021.04.22'

zipapps/__main__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,15 @@ def main():
167167
dest='lazy_install',
168168
help='Install packages with pip while running, which means '
169169
'requirements will not be install into pyz file.')
170+
parser.add_argument(
171+
'-pva',
172+
'--python-version-accuracy',
173+
'--python-version-slice',
174+
default='2',
175+
dest='python_version_slice',
176+
help='Only work for lazy-install mode, then `pip` target folders differ '
177+
'according to sys.version_info[:_slice], defaults to 2, which means '
178+
'3.8.3 equals to 3.8.4 for same version accuracy 3.8')
170179
parser.add_argument('--sys-paths',
171180
'--sys-path',
172181
'--py-path',
@@ -196,6 +205,7 @@ def main():
196205
env_paths=args.env_paths,
197206
lazy_install=args.lazy_install,
198207
sys_paths=args.sys_paths,
208+
python_version_slice=int(args.python_version_slice),
199209
)
200210

201211

zipapps/ensure_zipapps_template.py

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# -*- coding: utf-8 -*-
2+
13
import os
24
import sys
35
from pathlib import Path
@@ -19,15 +21,27 @@ def ensure_path(path):
1921
return _cache_folder_path
2022

2123

22-
def rm_dir(dir_path: Path):
24+
def rm_dir_and_file(path: Path):
2325
for _ in range(3):
2426
try:
25-
if not dir_path.is_dir():
27+
if path.is_dir():
28+
rmtree(str(path.absolute()))
29+
elif path.is_file():
30+
path.unlink()
31+
else:
2632
break
27-
# remove the exist folder
28-
rmtree(dir_path)
2933
except FileNotFoundError:
3034
break
35+
else:
36+
return False
37+
return True
38+
39+
40+
def clear_old_cache(_cache_folder_path: Path, LAZY_PIP_DIR_NAME=''):
41+
for path in _cache_folder_path.glob('*'):
42+
if path.name == LAZY_PIP_DIR_NAME:
43+
continue
44+
rm_dir_and_file(path)
3145

3246

3347
def prepare_path():
@@ -42,14 +56,25 @@ def prepare_path():
4256

4357
_cache_folder_path = ensure_path(_cache_folder)
4458
_cache_folder_path = _cache_folder_path / zip_file_path.stem
59+
_cache_folder_path.mkdir(parents=True, exist_ok=True)
4560
_cache_folder_path_str = str(_cache_folder_path.absolute())
4661
_zipapps_python_path_list.insert(0, _cache_folder_path_str)
4762
ts_file_name = '_zip_time_{ts}'
63+
LAZY_PIP_DIR_NAME = r'''{LAZY_PIP_DIR_NAME}'''
64+
if LAZY_PIP_DIR_NAME:
65+
import platform
66+
lazy_pip_dir = _cache_folder_path / LAZY_PIP_DIR_NAME
67+
# pip target isolation with by python version and platform
68+
platform_name = (platform.system() or '-')
69+
version_name = '.'.join(
70+
map(str, sys.version_info[:{python_version_slice}]))
71+
_pip_target = lazy_pip_dir / version_name / platform_name
72+
lazy_pip_dir_str = str(_pip_target.absolute())
73+
_zipapps_python_path_list.insert(1, lazy_pip_dir_str)
4874
if not (_cache_folder_path / ts_file_name).is_file():
4975
# check timestamp difference by file name, need to refresh _cache_folder
5076
# rm the folder
51-
rm_dir(_cache_folder_path)
52-
_cache_folder_path.mkdir(parents=True)
77+
clear_old_cache(_cache_folder_path, LAZY_PIP_DIR_NAME)
5378
_need_unzip_names = unzip.split(',')
5479
_need_unzip_names.append(ts_file_name)
5580
with ZipFile(zip_file_path, "r") as zf:
@@ -59,8 +84,7 @@ def prepare_path():
5984
if unzip == '*' or member.filename in _need_unzip_names or file_dir_name in _need_unzip_names:
6085
zf.extract(member, path=_cache_folder_path_str)
6186
# lazy pip install
62-
lazy_pip_dir = _cache_folder_path / r'''{LAZY_PIP_DIR_NAME}'''
63-
if lazy_pip_dir.is_dir():
87+
if LAZY_PIP_DIR_NAME and lazy_pip_dir.is_dir():
6488
try:
6589
import pip
6690
except ImportError:
@@ -69,7 +93,7 @@ def prepare_path():
6993
import subprocess
7094
shell_args = [
7195
sys.executable, '-m', 'pip', 'install', '--target',
72-
_cache_folder_path_str
96+
lazy_pip_dir_str
7397
] + {pip_args_repr}
7498
with subprocess.Popen(shell_args,
7599
cwd=_cache_folder_path_str) as proc:

zipapps/main.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ def prepare_entry(
6262
env_paths: str = '',
6363
pip_args: list = None,
6464
sys_paths: str = '',
65+
python_version_slice: int = 2,
6566
):
6667
unzip_names = set(unzip.split(',')) if unzip else set()
6768
warning_names: typing.Dict[str, dict] = {}
@@ -116,6 +117,7 @@ def prepare_entry(
116117
'LAZY_PIP_DIR_NAME': Config.LAZY_PIP_DIR_NAME,
117118
'pip_args_repr': repr(pip_args),
118119
'sys_paths': sys_paths,
120+
'python_version_slice': python_version_slice,
119121
}
120122
code = get_data('zipapps', '_entry_point.py').decode('u8')
121123
(cache_path / '__main__.py').write_text(code.format(**kwargs))
@@ -217,6 +219,7 @@ def create_app(
217219
env_paths: str = '',
218220
lazy_install: bool = False,
219221
sys_paths: str = '',
222+
python_version_slice: int = 2,
220223
):
221224
tmp_dir: tempfile.TemporaryDirectory = None
222225
try:
@@ -237,7 +240,7 @@ def create_app(
237240
)
238241
if lazy_install:
239242
sys.stderr.write(
240-
f'WARNING: `unzip` arg has been changed `{unzip}` => `*` for `lazy_install` is True\n'
243+
'WARNING: `unzip` has been changed to "*" while `lazy_install` is True.\n'
241244
)
242245
unzip = '*'
243246
# copy files to cache folder
@@ -252,7 +255,7 @@ def create_app(
252255
pip_args[index] = _r_path.as_posix()
253256
if not unzip_path:
254257
sys.stderr.write(
255-
f'WARNING: unzip path has been set to `SELF/{Config.DEFAULT_UNZIP_CACHE_PATH}` by default for `lazy_install` is True.\n'
258+
f'WARNING: unzip path has been set to `SELF/{Config.DEFAULT_UNZIP_CACHE_PATH}` while `lazy_install` is True and `unzip_path` is null.\n'
256259
)
257260
unzip_path = f'SELF/{Config.DEFAULT_UNZIP_CACHE_PATH}'
258261
else:
@@ -273,6 +276,7 @@ def create_app(
273276
env_paths=env_paths,
274277
pip_args=pip_args,
275278
sys_paths=sys_paths,
279+
python_version_slice=python_version_slice,
276280
)
277281
if compiled:
278282
if not unzip:

0 commit comments

Comments
 (0)