pyship 0.1.6__py3-none-any.whl → 0.1.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyship/_version_.py +1 -1
- pyship/create_launcher.py +2 -0
- pyship/download.py +18 -2
- pyship/launcher/launcher.py +6 -5
- pyship/pyship.py +3 -1
- {pyship-0.1.6.dist-info → pyship-0.1.7.dist-info}/METADATA +1 -1
- {pyship-0.1.6.dist-info → pyship-0.1.7.dist-info}/RECORD +10 -10
- {pyship-0.1.6.dist-info → pyship-0.1.7.dist-info}/LICENSE +0 -0
- {pyship-0.1.6.dist-info → pyship-0.1.7.dist-info}/WHEEL +0 -0
- {pyship-0.1.6.dist-info → pyship-0.1.7.dist-info}/top_level.txt +0 -0
pyship/_version_.py
CHANGED
|
@@ -2,7 +2,7 @@ from pyshipupdate import __author__ as pyship_author
|
|
|
2
2
|
|
|
3
3
|
__application_name__ = "pyship"
|
|
4
4
|
__author__ = pyship_author
|
|
5
|
-
__version__ = "0.1.
|
|
5
|
+
__version__ = "0.1.7"
|
|
6
6
|
__title__ = __application_name__
|
|
7
7
|
__author_email__ = "j@abel.co"
|
|
8
8
|
__url__ = "https://github.com/jamesabel/pyship"
|
pyship/create_launcher.py
CHANGED
|
@@ -4,6 +4,7 @@ import subprocess
|
|
|
4
4
|
|
|
5
5
|
from typeguard import typechecked
|
|
6
6
|
from balsa import get_logger
|
|
7
|
+
from semver import VersionInfo
|
|
7
8
|
|
|
8
9
|
from pyshipupdate import mkdirs
|
|
9
10
|
import pyship
|
|
@@ -99,6 +100,7 @@ def create_pyship_launcher(target_app_info: AppInfo, app_path_output: Path):
|
|
|
99
100
|
# avoid re-building launcher if its functionality wouldn't change
|
|
100
101
|
assert isinstance(target_app_info.author, str)
|
|
101
102
|
assert isinstance(target_app_info.is_gui, bool)
|
|
103
|
+
assert isinstance(target_app_info.version, VersionInfo)
|
|
102
104
|
metadata = calculate_metadata(target_app_info.name, target_app_info.author, target_app_info.version, Path(launcher_module_dir), icon_path, target_app_info.is_gui)
|
|
103
105
|
if not launcher_exe_path.exists() or metadata != load_metadata(app_path_output, metadata_filename):
|
|
104
106
|
pyship_print(f'building launcher ("{launcher_exe_path}")')
|
pyship/download.py
CHANGED
|
@@ -32,6 +32,22 @@ def file_download(url: str, destination_folder: Path, file_name: Path):
|
|
|
32
32
|
return destination_path
|
|
33
33
|
|
|
34
34
|
|
|
35
|
+
def is_within_directory(directory: Path, target: Path):
|
|
36
|
+
abs_directory = directory.absolute()
|
|
37
|
+
abs_target = target.absolute()
|
|
38
|
+
prefix = os.path.commonprefix([abs_directory, abs_target])
|
|
39
|
+
return prefix == str(abs_directory)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def safe_extract(tar, path: Path = Path(".")):
|
|
43
|
+
# for CVE-2007-4559
|
|
44
|
+
for member in tar.getmembers():
|
|
45
|
+
member_path = Path(path, member.name)
|
|
46
|
+
if not is_within_directory(path, member_path):
|
|
47
|
+
raise Exception("Attempted Path Traversal in Tar File")
|
|
48
|
+
tar.extractall(path, None, numeric_owner=False)
|
|
49
|
+
|
|
50
|
+
|
|
35
51
|
@typechecked
|
|
36
52
|
def extract(source_folder: Path, source_file: Path, destination_folder: Path):
|
|
37
53
|
mkdirs(destination_folder, remove_first=True)
|
|
@@ -43,9 +59,9 @@ def extract(source_folder: Path, source_file: Path, destination_folder: Path):
|
|
|
43
59
|
zf.extractall(destination_folder)
|
|
44
60
|
elif source_file.suffix == ".tgz":
|
|
45
61
|
with tarfile.open(source) as tf:
|
|
46
|
-
tf
|
|
62
|
+
safe_extract(tf, destination_folder)
|
|
47
63
|
elif source_file.suffix == ".gz":
|
|
48
64
|
with tarfile.open(source) as tf:
|
|
49
|
-
tf
|
|
65
|
+
safe_extract(tf, destination_folder)
|
|
50
66
|
else:
|
|
51
67
|
raise Exception(f"Unsupported file type {source_file.suffix} ({source_file})")
|
pyship/launcher/launcher.py
CHANGED
|
@@ -6,6 +6,7 @@ import appdirs
|
|
|
6
6
|
import re
|
|
7
7
|
import logging
|
|
8
8
|
import subprocess
|
|
9
|
+
from typing import Union
|
|
9
10
|
|
|
10
11
|
from ismain import is_main
|
|
11
12
|
from balsa import HandlerType, get_logger
|
|
@@ -73,7 +74,7 @@ def setup_logging(is_gui: bool, report_exceptions: bool) -> bool:
|
|
|
73
74
|
return verbose
|
|
74
75
|
|
|
75
76
|
|
|
76
|
-
def launch(additional_path: Path = None, app_dir: Path = None) -> int:
|
|
77
|
+
def launch(additional_path: Union[Path, None] = None, app_dir: Union[Path, None] = None) -> int:
|
|
77
78
|
"""
|
|
78
79
|
launch the pyship app
|
|
79
80
|
:param additional_path - additional search path for app (mainly for testing)
|
|
@@ -97,8 +98,8 @@ def launch(additional_path: Path = None, app_dir: Path = None) -> int:
|
|
|
97
98
|
target_app_author = __author__
|
|
98
99
|
|
|
99
100
|
for metadata_file_path in app_dir.glob("*_metadata.json"):
|
|
100
|
-
with metadata_file_path.open() as
|
|
101
|
-
metadata = json.load(
|
|
101
|
+
with metadata_file_path.open() as metadata_file:
|
|
102
|
+
metadata = json.load(metadata_file)
|
|
102
103
|
target_app_name = metadata.get("app")
|
|
103
104
|
target_app_author = metadata.get("author", target_app_author)
|
|
104
105
|
is_gui = metadata.get("is_gui", is_gui)
|
|
@@ -187,7 +188,7 @@ def launch(additional_path: Path = None, app_dir: Path = None) -> int:
|
|
|
187
188
|
log_function(out)
|
|
188
189
|
|
|
189
190
|
# log, and possibly print, each line of output from the process
|
|
190
|
-
for name, std_x,
|
|
191
|
+
for name, std_x, sys_f in [("stdout", std_out, sys.stdout), ("stderr", std_err, sys.stderr)]:
|
|
191
192
|
if std_x is not None and len(std_x.strip()) > 0:
|
|
192
193
|
for so_line in std_x.splitlines():
|
|
193
194
|
so_line_strip = so_line.strip()
|
|
@@ -195,7 +196,7 @@ def launch(additional_path: Path = None, app_dir: Path = None) -> int:
|
|
|
195
196
|
log.info(f"{name}:{so_line_strip}") # when logging, start with the name of the output string (stdout, stderr)
|
|
196
197
|
|
|
197
198
|
# output stdout, stderr that came (directly) from the process
|
|
198
|
-
print(std_x, file=
|
|
199
|
+
print(std_x, file=sys_f)
|
|
199
200
|
|
|
200
201
|
log.info(f"{return_code=}")
|
|
201
202
|
|
pyship/pyship.py
CHANGED
|
@@ -7,6 +7,7 @@ from attr import attrs
|
|
|
7
7
|
from typeguard import typechecked
|
|
8
8
|
from awsimple import S3Access
|
|
9
9
|
from balsa import get_logger
|
|
10
|
+
from semver import VersionInfo
|
|
10
11
|
|
|
11
12
|
from pyship import __application_name__ as pyship_application_name
|
|
12
13
|
from pyship import __author__ as pyship_author
|
|
@@ -32,7 +33,7 @@ class PyShip:
|
|
|
32
33
|
cloud_id: Union[str, None] = None # e.g. AWS Access Key ID
|
|
33
34
|
cloud_secret: Union[str, None] = None # e.g. AWS Secret Access Key
|
|
34
35
|
cloud_access: Union[PyShipCloud, None] = None # making this accessible outside this class aids in testing, especially when mocking
|
|
35
|
-
upload: bool = True # set to False to tell pyship to not attempt to perform file upload to the cloud (e.g. installer, clip files to AWS S3)
|
|
36
|
+
upload: bool = True # set to False in order to tell pyship to not attempt to perform file upload to the cloud (e.g. installer, clip files to AWS S3)
|
|
36
37
|
|
|
37
38
|
@typechecked
|
|
38
39
|
def ship(self) -> Path:
|
|
@@ -63,6 +64,7 @@ class PyShip:
|
|
|
63
64
|
clip_dir = create_clip(target_app_info, app_dir, True, Path(self.project_dir, self.dist_dir), self.cache_dir, self.find_links)
|
|
64
65
|
|
|
65
66
|
clip_file_path = create_clip_file(clip_dir) # create clip file
|
|
67
|
+
assert isinstance(target_app_info.version, VersionInfo)
|
|
66
68
|
installer_exe_path = run_nsis(target_app_info, target_app_info.version, app_dir) # create installer
|
|
67
69
|
|
|
68
70
|
if self.upload:
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
pyship/__init__.py,sha256=x7jisL_D4Wuyw5tfmyLz57WlRLX9QQYpkb3Vne_J3W0,1336
|
|
2
2
|
pyship/__main__.py,sha256=mn9BUEsE52gyI7SLrXh_dBxLwD335iVG_iqRCNqocq4,86
|
|
3
|
-
pyship/_version_.py,sha256=
|
|
3
|
+
pyship/_version_.py,sha256=_lpeahvzNw7RLUbyDSBVoziS-tN4LJxasGcrBlkALBo,389
|
|
4
4
|
pyship/app_info.py,sha256=mhbwJHkoWek1FRv9dwRlrf_8ssNK-UtDhvnZ-8kWQFo,7347
|
|
5
5
|
pyship/arguments.py,sha256=p4cA8FwbNSZqg4XI6LsYit1QN7TpAWWZH2xrgLf-f-g,1882
|
|
6
6
|
pyship/atomic_zip.py,sha256=HEZuHEatyWAGqZcvS_EoByQQRCQph5ajkszfZ3OxnRU,1366
|
|
7
7
|
pyship/clip.py,sha256=kmdbnzJbgD9ggBEUqs73_p2kac2looaOeGItk9N50xo,8237
|
|
8
8
|
pyship/cloud.py,sha256=FDJvTlURrtA00z3a8fWkR_K7YzURNKnd0NypJQKxHAo,1264
|
|
9
9
|
pyship/constants.py,sha256=FVkr1c9XDkaXyQnL1bEP-dWSbk4SUkrRuVQYPIxHMaA,19
|
|
10
|
-
pyship/create_launcher.py,sha256=
|
|
11
|
-
pyship/download.py,sha256=
|
|
10
|
+
pyship/create_launcher.py,sha256=HQby4dmnBnSbohspex8TaCgu-jEaEjLb1QGE76D_ky4,6247
|
|
11
|
+
pyship/download.py,sha256=QHbdVwxLNBToMEC0tOF2ZquDpoydRu0-cj7LOERr5Q4,2460
|
|
12
12
|
pyship/get-pip.py,sha256=BC5otuX7znr6F8Llv4oQLwLDp22R0GwHmThf0UIHRHI,1829954
|
|
13
13
|
pyship/logging.py,sha256=cIB7487tN8TsKeDHwwzjA30rHRW5Ci5GA5uPbaEXaY0,966
|
|
14
14
|
pyship/main.py,sha256=pALpy8ooWsKkUpWUtGWO567I9u1fbIFWdBU0dnWm2K4,866
|
|
15
15
|
pyship/nsis.py,sha256=QhG8FMwFZRsoPQbntCSCr5av1NNqgjksinhfxXpc0Vg,12744
|
|
16
16
|
pyship/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
17
|
pyship/pyship.ico,sha256=9oiMtmA7NiBmxM0NmMJQU5jXmnbEWCdqTaO3XvJ7ozY,103500
|
|
18
|
-
pyship/pyship.py,sha256=
|
|
18
|
+
pyship/pyship.py,sha256=vMeFK940mIReKTMy0x-hFvTHXfATt97tL5knyK7R_9I,5554
|
|
19
19
|
pyship/pyship_custom_print.py,sha256=WHgZNZNiKwQjKmxdsBrn7aJfG5VJdfQ1-9AC_tg5MxE,651
|
|
20
20
|
pyship/pyship_exceptions.py,sha256=teUOh3FuRUU9hyv7L4owACQZPWNdwpYTEz6l-Ao35nw,959
|
|
21
21
|
pyship/pyship_get_icon.py,sha256=FwglA67RXX0lhW9baIGsQy3_T4hVsVkBmvAhPyuhHLo,2016
|
|
@@ -24,13 +24,13 @@ pyship/pyship_subprocess.py,sha256=hH4MW_j2zLJLDmLDkkl2JWupXrvSemAeCPAEtPdSGyk,3
|
|
|
24
24
|
pyship/launcher/__init__.py,sha256=25vVghziYIHDBA0mCaGqhj6hWxxjQqlm4LrY0Hem0YY,245
|
|
25
25
|
pyship/launcher/__main__.py,sha256=KhFSf1RU5Cj15y0c4FlzvIvDpWWi9NKYy0gzJ-w7KQE,115
|
|
26
26
|
pyship/launcher/hash.py,sha256=THEh8G-StEJeh5tH24RnAQpYB0Zv1nnBwqOoStN6_NY,1153
|
|
27
|
-
pyship/launcher/launcher.py,sha256=
|
|
27
|
+
pyship/launcher/launcher.py,sha256=AmjAwt8VbQTOVmRC-vUd7Cm-KS3ALYe1RLSxmcutthY,10359
|
|
28
28
|
pyship/launcher/metadata.py,sha256=vkf70w_eX8EZbMDHFKqBWW1kn0RyZl70z4DGsLCahmA,1666
|
|
29
29
|
pyship/launcher/restart_monitor.py,sha256=jfzchLxGuC_xUNdPAr849FhAdozJ6BX9M-gqLd-gGIA,952
|
|
30
30
|
pyship/patch/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
31
31
|
pyship/patch/pyship_patch.py,sha256=KgObD80QPeOhu1KCdhdQzn-4AnyzCUxIGWKj22BjTCc,1256
|
|
32
|
-
pyship-0.1.
|
|
33
|
-
pyship-0.1.
|
|
34
|
-
pyship-0.1.
|
|
35
|
-
pyship-0.1.
|
|
36
|
-
pyship-0.1.
|
|
32
|
+
pyship-0.1.7.dist-info/LICENSE,sha256=wJpPh6rC_YhbTZ7ZIy1VjrqeLdJ8Pz0ppx2MUi7s8Dg,1088
|
|
33
|
+
pyship-0.1.7.dist-info/METADATA,sha256=0vrDjPX1xcZbErIhF_WDmKFPVRgviw4a0iJhEPLUm00,1361
|
|
34
|
+
pyship-0.1.7.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
|
35
|
+
pyship-0.1.7.dist-info/top_level.txt,sha256=mlozeft-UInVAceSajzNvtkn2vPa8El9j0RulsTVtlU,7
|
|
36
|
+
pyship-0.1.7.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|