pyship 0.1.5__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 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"
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/app_info.py CHANGED
@@ -1,6 +1,9 @@
1
+ import os
1
2
  from pathlib import Path
2
3
  from dataclasses import dataclass
3
4
  from typing import Union
5
+ import subprocess
6
+ import sys
4
7
 
5
8
  import toml
6
9
  from semver import VersionInfo
@@ -49,13 +52,11 @@ def get_app_info_py_project(app_info: AppInfo, target_app_project_dir: Path) ->
49
52
  pyproject = toml.load(f)
50
53
  project_section = pyproject.get("project")
51
54
  if project_section is not None:
52
-
53
55
  app_info.name = project_section.get("name")
54
56
  app_info.author = project_section.get("author") # app author
55
57
 
56
58
  tool_section = pyproject.get("tool")
57
59
  if tool_section is not None:
58
-
59
60
  if app_info.name is None:
60
61
  # The user didn't provide a separate [project].name so let's try to get it from what flit writes out at [tool.flit.metadata]/module.
61
62
  # This is all we want or need to get from tool.flit.metadata since the remainder of the fields will be in the package distribution.
@@ -86,6 +87,16 @@ def get_app_info_wheel(app_info: AppInfo, dist_path: Path) -> AppInfo:
86
87
  return app_info
87
88
 
88
89
 
90
+ @typechecked
91
+ def run_script(target_app_project_dir: Path, script_file_name: str):
92
+ script_path = Path(target_app_project_dir, script_file_name)
93
+ if script_path.exists():
94
+ pyship_print(f'running "{script_file_name}" (cwd="{target_app_project_dir}")')
95
+ make_venv_process = subprocess.run(script_file_name, cwd=str(target_app_project_dir), capture_output=True)
96
+ log.info(make_venv_process.stdout)
97
+ log.info(make_venv_process.stderr)
98
+
99
+
89
100
  @typechecked
90
101
  def get_app_info(target_app_project_dir: Path, target_app_dist_dir: Path) -> AppInfo:
91
102
  """
@@ -103,8 +114,22 @@ def get_app_info(target_app_project_dir: Path, target_app_dist_dir: Path) -> App
103
114
  if app_info.name is None:
104
115
  log.error(f"{app_info.name=} {target_app_project_dir=}")
105
116
  else:
117
+ wheel_glob = f"{app_info.name}*.whl"
118
+ wheel_list = list(target_app_dist_dir.glob(wheel_glob))
119
+ if len(wheel_list) < 1:
120
+ # No wheel file exists, but if there's a .bat file to build it, try that. In general the pyship user should have already created their wheel, but this is also
121
+ # handy for testing so the pyship repo can be cloned and pytest run, without otherwise having to build the test app's wheel.
122
+
123
+ venvs = list(Path(target_app_project_dir).glob("*venv")) # does venv or .venv exist?
124
+ if len(venvs) < 1:
125
+ # Try to build the venv if it doesn't exist. Note that this uses specific script file names, but they can be set via env var.
126
+ run_script(target_app_project_dir, os.environ.get("PYSHIP_MAKE_VENV_SCRIPT", "make_venv.bat")) # will be .sh for Linux/MacOS whenever they're supported ...
127
+
128
+ # run script to build the wheel
129
+ run_script(target_app_project_dir, os.environ.get("PYSHIP_BUILD_SCRIPT", "build.bat")) # will be .sh for Linux/MacOS whenever they're supported ...
130
+
131
+ wheel_list = list(target_app_dist_dir.glob(wheel_glob)) # try again to find the wheel
106
132
 
107
- wheel_list = list(target_app_dist_dir.glob(f"{app_info.name}*.whl"))
108
133
  if len(wheel_list) == 0:
109
134
  log.error(f"{app_info.name} : no wheel at {target_app_dist_dir} ({target_app_dist_dir.absolute()})")
110
135
  elif len(wheel_list) > 1:
pyship/arguments.py CHANGED
@@ -8,7 +8,6 @@ from pyship import __name__, __version__, DEFAULT_DIST_DIR_NAME
8
8
 
9
9
 
10
10
  def get_arguments() -> Any:
11
-
12
11
  parser = argparse.ArgumentParser(prog=__name__, formatter_class=argparse.ArgumentDefaultsHelpFormatter)
13
12
 
14
13
  parser.add_argument("-n", "--name", help="name of target application to ship (if not provided elsewhere such as in pyproject.toml at: [project] name=<name>")
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
@@ -30,7 +31,6 @@ def create_pyship_launcher(target_app_info: AppInfo, app_path_output: Path):
30
31
  if target_app_info.name is None or len(target_app_info.name) < 1:
31
32
  log.error(f"{target_app_info.name=}")
32
33
  else:
33
-
34
34
  metadata_filename = f"{target_app_info.name}_metadata.json"
35
35
 
36
36
  # create launcher
@@ -52,7 +52,6 @@ def create_pyship_launcher(target_app_info: AppInfo, app_path_output: Path):
52
52
  if python_interpreter_path is None or len(python_interpreter_path) < 1:
53
53
  log.error("python interpreter path not found")
54
54
  else:
55
-
56
55
  mkdirs(app_path_output)
57
56
 
58
57
  explicit_modules_to_import = [
@@ -82,17 +81,28 @@ def create_pyship_launcher(target_app_info: AppInfo, app_path_output: Path):
82
81
  command_line.append("--noconsole")
83
82
  # command_line.extend(["--debug", "all"]) # todo: remove once we get the launcher working again
84
83
  site_packages_dir = Path(venv_dir, "Lib", "site-packages")
85
- launcher_path = Path(site_packages_dir, pyship_application_name, launcher_application_name, f"{launcher_application_name}.py").absolute()
86
- if not launcher_path.exists():
87
- log.error(f"{launcher_path} does not exist")
88
- command_line.append(str(launcher_path))
84
+
85
+ # find the launcher source code, so we can make an executable from it
86
+ launcher_source_path = None
87
+ launcher_candidate_parents = (site_packages_dir, Path())
88
+ for parent in launcher_candidate_parents:
89
+ source_candidate = Path(parent, pyship_application_name, launcher_application_name, f"{launcher_application_name}.py").absolute()
90
+ if source_candidate.exists():
91
+ launcher_source_path = source_candidate
92
+ break
93
+ if launcher_source_path is None:
94
+ log.fatal(f"could not find launcher path in {launcher_candidate_parents=}")
95
+ return False
96
+ else:
97
+ log.info(f"{launcher_source_path=}")
98
+ command_line.append(str(launcher_source_path))
89
99
 
90
100
  # avoid re-building launcher if its functionality wouldn't change
91
101
  assert isinstance(target_app_info.author, str)
92
102
  assert isinstance(target_app_info.is_gui, bool)
103
+ assert isinstance(target_app_info.version, VersionInfo)
93
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)
94
105
  if not launcher_exe_path.exists() or metadata != load_metadata(app_path_output, metadata_filename):
95
-
96
106
  pyship_print(f'building launcher ("{launcher_exe_path}")')
97
107
  log.info(f"project_dir={str(target_app_info.project_dir)}")
98
108
  log.info(f"{command_line=}")
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.extractall(destination_folder)
62
+ safe_extract(tf, destination_folder)
47
63
  elif source_file.suffix == ".gz":
48
64
  with tarfile.open(source) as tf:
49
- tf.extractall(destination_folder)
65
+ safe_extract(tf, destination_folder)
50
66
  else:
51
67
  raise Exception(f"Unsupported file type {source_file.suffix} ({source_file})")
@@ -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
@@ -27,7 +28,6 @@ launcher_verbose_string = "--launcher_verbose"
27
28
 
28
29
 
29
30
  def setup_logging(is_gui: bool, report_exceptions: bool) -> bool:
30
-
31
31
  verbose = len(sys.argv) > 1 and sys.argv[1].lower() == launcher_verbose_string
32
32
 
33
33
  pyship_log = PyshipLog(launcher_application_name, __author__, gui=is_gui, verbose=verbose)
@@ -74,7 +74,7 @@ def setup_logging(is_gui: bool, report_exceptions: bool) -> bool:
74
74
  return verbose
75
75
 
76
76
 
77
- 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:
78
78
  """
79
79
  launch the pyship app
80
80
  :param additional_path - additional search path for app (mainly for testing)
@@ -98,8 +98,8 @@ def launch(additional_path: Path = None, app_dir: Path = None) -> int:
98
98
  target_app_author = __author__
99
99
 
100
100
  for metadata_file_path in app_dir.glob("*_metadata.json"):
101
- with metadata_file_path.open() as f:
102
- metadata = json.load(f)
101
+ with metadata_file_path.open() as metadata_file:
102
+ metadata = json.load(metadata_file)
103
103
  target_app_name = metadata.get("app")
104
104
  target_app_author = metadata.get("author", target_app_author)
105
105
  is_gui = metadata.get("is_gui", is_gui)
@@ -112,7 +112,6 @@ def launch(additional_path: Path = None, app_dir: Path = None) -> int:
112
112
  if target_app_name is None:
113
113
  log.error(f'could not derive target app name in {app_dir}")')
114
114
  else:
115
-
116
115
  log.info(f"{target_app_name=}")
117
116
 
118
117
  # 1) find the latest <application_name>_<version>
@@ -125,7 +124,6 @@ def launch(additional_path: Path = None, app_dir: Path = None) -> int:
125
124
  restart_monitor = RestartMonitor()
126
125
 
127
126
  while (return_code is None or return_code == restart_return_code) and not restart_monitor.excessive():
128
-
129
127
  restart_monitor.add()
130
128
 
131
129
  # todo: put finding the most recent app version in a function - I'll pretty sure this is done other places. Also, it allows a unit test to be written for it.
@@ -171,7 +169,6 @@ def launch(additional_path: Path = None, app_dir: Path = None) -> int:
171
169
  cmd.append(arg) # pass along any arguments to the target application
172
170
  log.info(f"{cmd}")
173
171
  try:
174
-
175
172
  # todo: this should work with PyInstaller, but it doesn't and I don't know why:
176
173
  # return_code, _, _ = subprocess_run(cmd, cwd=python_exe_path.parent, mute_output=is_gui) # if app returns "restart_value" then it wants to be restarted
177
174
 
@@ -191,7 +188,7 @@ def launch(additional_path: Path = None, app_dir: Path = None) -> int:
191
188
  log_function(out)
192
189
 
193
190
  # log, and possibly print, each line of output from the process
194
- for name, std_x, f in [("stdout", std_out, sys.stdout), ("stderr", std_err, sys.stderr)]:
191
+ for name, std_x, sys_f in [("stdout", std_out, sys.stdout), ("stderr", std_err, sys.stderr)]:
195
192
  if std_x is not None and len(std_x.strip()) > 0:
196
193
  for so_line in std_x.splitlines():
197
194
  so_line_strip = so_line.strip()
@@ -199,7 +196,7 @@ def launch(additional_path: Path = None, app_dir: Path = None) -> int:
199
196
  log.info(f"{name}:{so_line_strip}") # when logging, start with the name of the output string (stdout, stderr)
200
197
 
201
198
  # output stdout, stderr that came (directly) from the process
202
- print(std_x, file=f)
199
+ print(std_x, file=sys_f)
203
200
 
204
201
  log.info(f"{return_code=}")
205
202
 
pyship/main.py CHANGED
@@ -2,7 +2,6 @@ from pyship import PyShip, __application_name__, __author__, PyshipLog, get_argu
2
2
 
3
3
 
4
4
  def main():
5
-
6
5
  args = get_arguments()
7
6
 
8
7
  pyship_log = PyshipLog(__application_name__, __author__)
pyship/nsis.py CHANGED
@@ -48,7 +48,6 @@ def run_nsis(target_app_info: AppInfo, target_app_version: VersionInfo, app_dir:
48
48
  license_file_name = "LICENSE"
49
49
 
50
50
  if Path(target_app_info.project_dir, license_file_name).exists():
51
-
52
51
  nsis_file_path = Path(target_app_info.project_dir, f"{target_app_info.name}.nsi").absolute()
53
52
  pyship_print(f'building installer "{nsis_file_path}" ("{nsis_file_path.absolute()}")')
54
53
 
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
@@ -21,7 +22,6 @@ log = get_logger(pyship_application_name)
21
22
 
22
23
  @attrs(auto_attribs=True)
23
24
  class PyShip:
24
-
25
25
  project_dir: Path = Path() # target app project dir, e.g. the "home" directory of the project. If not set, current working directory is used.
26
26
  dist_dir: Path = Path(DEFAULT_DIST_DIR_NAME) # many packaging tools (e.g filt, etc.) use "dist" as the package destination directory
27
27
  find_links: list = list() # extra dirs for pip to use for packages not yet on PyPI (e.g. under local development)
@@ -33,7 +33,7 @@ class PyShip:
33
33
  cloud_id: Union[str, None] = None # e.g. AWS Access Key ID
34
34
  cloud_secret: Union[str, None] = None # e.g. AWS Secret Access Key
35
35
  cloud_access: Union[PyShipCloud, None] = None # making this accessible outside this class aids in testing, especially when mocking
36
- 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)
37
37
 
38
38
  @typechecked
39
39
  def ship(self) -> Path:
@@ -55,7 +55,6 @@ class PyShip:
55
55
  elif target_app_info.name is None:
56
56
  raise PyshipNoAppName
57
57
  else:
58
-
59
58
  app_dir = Path(self.project_dir, APP_DIR_NAME, target_app_info.name).absolute()
60
59
 
61
60
  mkdirs(app_dir, remove_first=True)
@@ -65,13 +64,13 @@ class PyShip:
65
64
  clip_dir = create_clip(target_app_info, app_dir, True, Path(self.project_dir, self.dist_dir), self.cache_dir, self.find_links)
66
65
 
67
66
  clip_file_path = create_clip_file(clip_dir) # create clip file
67
+ assert isinstance(target_app_info.version, VersionInfo)
68
68
  installer_exe_path = run_nsis(target_app_info, target_app_info.version, app_dir) # create installer
69
69
 
70
70
  if self.upload:
71
71
  if self.cloud_profile is None and self.cloud_id is None:
72
72
  pyship_print("no cloud access provided - will not attempt upload")
73
73
  else:
74
-
75
74
  # if cloud bucket not given we'll try to use the project name
76
75
  assert isinstance(target_app_info.name, str)
77
76
  assert isinstance(target_app_info.author, str)
@@ -48,7 +48,6 @@ def subprocess_run(
48
48
  log.info(f"{cmd=}")
49
49
 
50
50
  try:
51
-
52
51
  if isinstance(cwd, NullPath):
53
52
  target_process = subprocess.run(cmd, env=run_env, capture_output=True, text=True)
54
53
  else:
@@ -1,50 +1,47 @@
1
- Metadata-Version: 2.1
2
- Name: pyship
3
- Version: 0.1.5
4
- Summary: freezer, installer and updater for Python applications
5
- Home-page: https://github.com/jamesabel/pyship
6
- Author: abel
7
- Author-email: j@abel.co
8
- License: MIT License
9
- Download-URL: https://github.com/jamesabel/pyship
10
- Keywords: freezer,installer,ship
11
- Platform: UNKNOWN
12
- Description-Content-Type: text/markdown
13
- License-File: LICENSE
14
- Requires-Dist: setuptools
15
- Requires-Dist: wheel
16
- Requires-Dist: ismain
17
- Requires-Dist: balsa
18
- Requires-Dist: requests
19
- Requires-Dist: attrs
20
- Requires-Dist: typeguard
21
- Requires-Dist: toml
22
- Requires-Dist: pyinstaller
23
- Requires-Dist: semver
24
- Requires-Dist: python-dateutil
25
- Requires-Dist: wheel-inspect
26
- Requires-Dist: boto3
27
- Requires-Dist: awsimple
28
- Requires-Dist: pyshipupdate
29
-
30
-
31
- # PyShip
32
-
33
- Enables shipping a python application to end users.
34
-
35
- ## PyShip's Major Features
36
-
37
- * Freeze practically any Python application
38
- * Creates an installer
39
- * Uploads application installer and updates to the cloud
40
- * Automatic application updating in the background (no user intervention)
41
- * OS native application (e.g. .exe for Windows)
42
- * Run on OS startup option
43
-
44
- ## Documentation and Examples
45
-
46
- [Learn PyShip By Example](https://github.com/jamesabel/pyshipexample)
47
-
48
- [Short video on pyship given at Pyninsula](https://abelpublic.s3.us-west-2.amazonaws.com/pyship_pyninsula_10_2020.mkv)
49
-
50
-
1
+ Metadata-Version: 2.1
2
+ Name: pyship
3
+ Version: 0.1.7
4
+ Summary: freezer, installer and updater for Python applications
5
+ Home-page: https://github.com/jamesabel/pyship
6
+ Download-URL: https://github.com/jamesabel/pyship
7
+ Author: abel
8
+ Author-email: j@abel.co
9
+ License: MIT License
10
+ Keywords: freezer,installer,ship
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: setuptools
14
+ Requires-Dist: wheel
15
+ Requires-Dist: ismain
16
+ Requires-Dist: balsa
17
+ Requires-Dist: requests
18
+ Requires-Dist: attrs
19
+ Requires-Dist: typeguard
20
+ Requires-Dist: toml
21
+ Requires-Dist: pyinstaller
22
+ Requires-Dist: semver
23
+ Requires-Dist: python-dateutil
24
+ Requires-Dist: wheel-inspect
25
+ Requires-Dist: boto3
26
+ Requires-Dist: awsimple
27
+ Requires-Dist: pyshipupdate
28
+
29
+
30
+ # PyShip
31
+
32
+ Enables shipping a python application to end users.
33
+
34
+ ## PyShip's Major Features
35
+
36
+ * Freeze practically any Python application
37
+ * Creates an installer
38
+ * Uploads application installer and updates to the cloud
39
+ * Automatic application updating in the background (no user intervention)
40
+ * OS native application (e.g. .exe for Windows)
41
+ * Run on OS startup option
42
+
43
+ ## Documentation and Examples
44
+
45
+ [Learn PyShip By Example](https://github.com/jamesabel/pyshipexample)
46
+
47
+ [Short video on pyship given at Pyninsula](https://abelpublic.s3.us-west-2.amazonaws.com/pyship_pyninsula_10_2020.mkv)
@@ -1,36 +1,36 @@
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=D-ZW-vNozOI_bW5PUvUySqLWhOZykPJFQ6HwxKia8pk,389
4
- pyship/app_info.py,sha256=ttfE5pLovAJoO0ZyfODIatmw5RUSi9lAg99jxBpN64Y,5696
5
- pyship/arguments.py,sha256=c0LRuo562EF6r7eRdxY_AMxgcLzJYMd3WP67CoskBeY,1884
3
+ pyship/_version_.py,sha256=_lpeahvzNw7RLUbyDSBVoziS-tN4LJxasGcrBlkALBo,389
4
+ pyship/app_info.py,sha256=mhbwJHkoWek1FRv9dwRlrf_8ssNK-UtDhvnZ-8kWQFo,7347
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=hM3tCsLeUrA9bPTGVFQZZawTkaWKSVnGq_anBLLzClo,5623
11
- pyship/download.py,sha256=inG18XKZ1qhOam27prKT0cTUx1IXRQooUPiIezZ_xf8,1871
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
- pyship/main.py,sha256=EjwMnLQ3TC01uzqzn8s2Pd38uVHxAh5v19lrQLsDC08,868
15
- pyship/nsis.py,sha256=Rvlf7xFx3BSfuZmhgzb6CTgObPMoaGYxFP2zSsDjlDI,12746
14
+ pyship/main.py,sha256=pALpy8ooWsKkUpWUtGWO567I9u1fbIFWdBU0dnWm2K4,866
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=0BZVBb3h_TB-8af25zKDLrt0W9b0ndS40INtJJzn5Wo,5450
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
22
22
  pyship/pyship_path.py,sha256=RpU2n7pWXTr0501S7U8KxWCpBc8jOqKPuaX0X6IWPI8,262
23
- pyship/pyship_subprocess.py,sha256=wE7T9IFAaby7iKA95yGWOln_7zJWnuXb-ogDcjmGq48,3214
23
+ pyship/pyship_subprocess.py,sha256=hH4MW_j2zLJLDmLDkkl2JWupXrvSemAeCPAEtPdSGyk,3212
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=UNL3Gs3zrlqVh_y1ixBPMuDXL4jb2PMHR0CTRUetniE,10283
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.5.dist-info/LICENSE,sha256=wJpPh6rC_YhbTZ7ZIy1VjrqeLdJ8Pz0ppx2MUi7s8Dg,1088
33
- pyship-0.1.5.dist-info/METADATA,sha256=TCkz3iLqyICby7PZgQk5Gnqgl5tzkYH3l1SfIDth7WY,1334
34
- pyship-0.1.5.dist-info/WHEEL,sha256=OqRkF0eY5GHssMorFjlbTIq072vpHpF60fIQA6lS9xA,92
35
- pyship-0.1.5.dist-info/top_level.txt,sha256=mlozeft-UInVAceSajzNvtkn2vPa8El9j0RulsTVtlU,7
36
- pyship-0.1.5.dist-info/RECORD,,
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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.36.2)
2
+ Generator: bdist_wheel (0.40.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5