def main(): parser = argparse.ArgumentParser(description='exxo builder', prog='exxo') parser.add_argument('-r', '--requirement', action='append', default=[], help='pip package name') parser.add_argument('source_path', help='source package directory') parser.add_argument('main', help='main function: package.module:function') parser.add_argument('dest_bin', help='target binary') args = parser.parse_args() builddir = Path('build') pip = str(builddir / 'bin' / 'pip') pyrun = builddir / 'bin' / 'pyrun3.4' # TODO: fixed py version # install_path = tempfile.mkdtemp() install_path = builddir / 'install' pip_root = install_path / 'pip_root' pip_root.mkdir(parents=True, exist_ok=True) zip_file = install_path / 'app.zip' try: cmd = [pip, 'install', '--target', str(pip_root)] if args.requirement: subprocess.check_call(cmd + args.requirement) # make sure pip undestands it as a local directory source_path = args.source_path.rstrip(os.sep) + os.sep subprocess.check_call(cmd + [source_path]) zipapp.create_archive(pip_root, zip_file, main=args.main) create_binary(Path(args.dest_bin), pyrun, zip_file) finally: # shutil.rmtree(install_path) pass
def _create_zipapp_archive(source_dir, entry_point, output_file): zipapp.create_archive( source_dir, interpreter='/usr/bin/env python3', main=entry_point, target=output_file, )
def main(): parser = argparse.ArgumentParser() parser.add_argument("--root", default=".") parser.add_argument("--dest") args = parser.parse_args() if args.dest is not None: dest = args.dest else: dest = os.path.join(args.root, "virtualenv.pyz") bio = io.BytesIO() with zipfile.ZipFile(bio, "w") as zipf: filenames = ["LICENSE.txt", "virtualenv.py"] for whl in os.listdir(os.path.join(args.root, "virtualenv_support")): filenames.append(os.path.join("virtualenv_support", whl)) for filename in filenames: zipf.write(os.path.join(args.root, filename), filename) zipf.writestr("__main__.py", "import virtualenv; virtualenv.main()") bio.seek(0) zipapp.create_archive(bio, dest) print("zipapp created at {}".format(dest))
def test_meson_zipapp(self): if is_windows(): raise unittest.SkipTest('NOT IMPLEMENTED') source = Path(__file__).resolve().parent.as_posix() target = self.tmpdir / 'meson.pyz' zipapp.create_archive(source=source, target=target, interpreter=python_command[0], main=None) self._run([target.as_posix(), '--help'])
def _build_zipapp( configuration: config.Config, zipapp_path: pathlib.Path, ) -> None: with tempfile.TemporaryDirectory() as temp_dir: temp_dir_path = pathlib.Path(temp_dir) # venv_dir_path = temp_dir_path.joinpath('venv') LOGGER.info("Creating virtual environment to build zipapp...") venv_context = venv_wrapper.create_venv(venv_dir_path) if venv_context: LOGGER.info("Virtual environment creation done.") # requirement_str_list = configuration['zipapp']['requirements'] # install_dir_path = temp_dir_path.joinpath('zipapp') LOGGER.info("Installing zipapp requirements...") python_exe = venv_context.env_exe # pylint: disable=no-member _do_pip_install( pathlib.Path(python_exe), install_dir_path, requirement_str_list, ) # zipapp_dir_path = zipapp_path.parent if not zipapp_dir_path.is_dir(): zipapp_dir_path.mkdir(parents=True) # zipapp.create_archive( install_dir_path, interpreter='/usr/bin/env python3', main='fj._cli.main:main', target=zipapp_path, )
def main(): """Main function""" # Create a temporary directory to build the app with tempfile.TemporaryDirectory() as build_dir: program_name = "k3s-helmchart-generate.py" shutil.copy(src=program_name, dst=os.path.join(build_dir, "__main__.py")) pip_install_cmd = [ sys.executable, "-m", "pip", "install", "--requirement", "requirements.txt", "--target", build_dir, ] subprocess.check_call(pip_install_cmd) zipapp.create_archive( source=build_dir, target=f"{program_name}z", interpreter="/usr/bin/env python3", compressed=True, )
def run(self): with TemporaryDirectory() as tmpdir: copytree('unicodemoticon', os.path.join(tmpdir, 'unicodemoticon')) fyle = os.path.join(tmpdir, '__main__.py') with open(fyle, 'w', encoding='utf-8') as entry: entry.write("import runpy\nrunpy.run_module('unicodemoticon')") create_archive(tmpdir, 'unicodemoticon.pyz', '/usr/bin/env python3')
def test_pack_to_fileobj(self): source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = io.BytesIO() zipapp.create_archive(str(source), target, interpreter='python') self.assertTrue(target.getvalue().startswith(b'#!python\n'))
def test_no_main(self): source = self.tmpdir / 'source' source.mkdir() (source / 'foo.py').touch() target = self.tmpdir / 'source.pyz' with self.assertRaises(zipapp.ZipAppError): zipapp.create_archive(str(source), str(target))
def test_main_and_main_py(self): source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' with self.assertRaises(zipapp.ZipAppError): zipapp.create_archive(str(source), str(target), main='pkg.mod:fn')
def test_create_archive_with_pathlib(self): source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(source, target) self.assertTrue(target.is_file())
def test_create_archive_default_target(self): source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() zipapp.create_archive(str(source)) expected_target = self.tmpdir / 'source.pyz' self.assertTrue(expected_target.is_file())
def test_no_shebang_is_not_executable(self): source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(str(source), str(target), interpreter=None) self.assertFalse(target.stat().st_mode & stat.S_IEXEC)
def make_archive(self): source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(source, target) return target
def test_meson_zipapp(self): if is_windows(): raise unittest.SkipTest('NOT IMPLEMENTED') source = Path(__file__).resolve().parent.as_posix() target = self.tmpdir / 'meson.pyz' zipapp.create_archive(source=source, target=target, interpreter=python_command[0], main=None) self._run([target.as_posix(), '--help'])
def cli_build_pyz(): this = Path(__file__) if this.suffix != ".py": raise Exception("can't packaging because already packaged") folder = this.parent target_folder = Path(tempfile.mkdtemp()) shutil.copytree(folder, target_folder / folder.name) (target_folder / folder.name / "__main__.py").rename(target_folder / "__main__.py") compileall.compile_dir(target_folder, legacy=True) def filter_func(file: Path): if "__pycache__" in file.parts: return False return file.suffix == ".pyc" pyz_path = folder.with_suffix(".pyz") zipapp.create_archive( target_folder, pyz_path, "/usr/bin/env python3.9", filter=filter_func, ) shutil.rmtree(target_folder) print(pyz_path)
def test_read_missing_shebang(self): source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(str(source), str(target)) self.assertEqual(zipapp.get_interpreter(str(target)), None)
def create_zip(): basedir = path.abspath(path.dirname(__file__)) zipapp.create_archive(source=basedir + '/build', target='vojpzipp.pyz', filter=file_filter, main='vojp.main:run')
def test_no_main(self): # Test that packing a directory with no __main__.py fails. source = self.tmpdir / 'source' source.mkdir() (source / 'foo.py').touch() target = self.tmpdir / 'source.pyz' with self.assertRaises(zipapp.ZipAppError): zipapp.create_archive(str(source), str(target))
def make_archive(self): # Test that an archive with no shebang line is not made executable. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(source, target) return target
def test_no_main(self): # Test that packing a directory with no __main__.py fails. source = self.tmpdir / 'source' source.mkdir() (source / 'foo.py').touch() target = self.tmpdir / 'source.pyz' with self.assertRaises(zipapp.ZipAppError): zipapp.create_archive(str(source), str(target))
def test_read_shebang(self): # Test that we can read the shebang line correctly. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(str(source), str(target), interpreter='python') self.assertEqual(zipapp.get_interpreter(str(target)), 'python')
def test_default_no_shebang(self): source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(str(source), str(target)) with target.open('rb') as f: self.assertNotEqual(f.read(2), b'#!')
def make_archive(self): # Test that an archive with no shebang line is not made executable. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(source, target) return target
def test_shebang_is_executable(self): # Test that an archive with a shebang line is made executable. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(str(source), str(target), interpreter='python') self.assertTrue(target.stat().st_mode & stat.S_IEXEC)
def test_create_archive_with_pathlib(self): # Test packing a directory using Path objects for source and target. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(source, target) self.assertTrue(target.is_file())
def test_create_archive_default_target(self): # Test packing a directory to the default name. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() zipapp.create_archive(str(source)) expected_target = self.tmpdir / 'source.pyz' self.assertTrue(expected_target.is_file())
def test_create_archive_with_pathlib(self): # Test packing a directory using Path objects for source and target. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(source, target) self.assertTrue(target.is_file())
def test_read_missing_shebang(self): # Test that reading the shebang line of a file without one returns None. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(str(source), str(target)) self.assertEqual(zipapp.get_interpreter(str(target)), None)
def test_read_missing_shebang(self): # Test that reading the shebang line of a file without one returns None. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(str(source), str(target)) self.assertEqual(zipapp.get_interpreter(str(target)), None)
def test_read_shebang(self): # Test that we can read the shebang line correctly. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(str(source), str(target), interpreter='python') self.assertEqual(zipapp.get_interpreter(str(target)), 'python')
def test_create_archive(self): # Test packing a directory. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(str(source), str(target)) self.assertTrue(target.is_file())
def test_create_archive(self): # Test packing a directory. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(str(source), str(target)) self.assertTrue(target.is_file())
def test_main_and_main_py(self): # Test that supplying a main argument with __main__.py fails. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' with self.assertRaises(zipapp.ZipAppError): zipapp.create_archive(str(source), str(target), main='pkg.mod:fn')
def test_no_shebang_is_not_executable(self): # Test that an archive with no shebang line is not made executable. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(str(source), str(target), interpreter=None) self.assertFalse(target.stat().st_mode & stat.S_IEXEC)
def test_pack_to_fileobj(self): # Test that we can pack to a file object. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = io.BytesIO() zipapp.create_archive(str(source), target, interpreter='python') self.assertTrue(target.getvalue().startswith(b'#!python\n'))
def test_read_from_pathobj(self): source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target1 = self.tmpdir / 'target1.pyz' target2 = self.tmpdir / 'target2.pyz' zipapp.create_archive(source, target1, interpreter='python') zipapp.create_archive(target1, target2, interpreter='python2.7') self.assertEqual(zipapp.get_interpreter(target2), 'python2.7')
def test_remove_shebang(self): source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(str(source), str(target), interpreter='python') new_target = self.tmpdir / 'changed.pyz' zipapp.create_archive(str(target), str(new_target), interpreter=None) self.assertEqual(zipapp.get_interpreter(str(new_target)), None)
def test_main_written(self): source = self.tmpdir / 'source' source.mkdir() (source / 'foo.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(str(source), str(target), main='pkg.mod:fn') with zipfile.ZipFile(str(target), 'r') as z: self.assertIn('__main__.py', z.namelist()) self.assertIn(b'pkg.mod.fn()', z.read('__main__.py'))
def test_default_no_shebang(self): # Test that no shebang line is written to the target by default. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(str(source), str(target)) with target.open('rb') as f: self.assertNotEqual(f.read(2), b'#!')
def __init__(self, mod_path, name, compressed=True, main_class="Main"): mod_path = mod_path.replace('\\', '/') while mod_path.endswith("/"): mod_path = mod_path[:-1] if not os.path.exists("build/"): os.makedirs("build/") create_archive(source=mod_path, target=f"build/{name}", compressed=compressed)
def test_main_only_written_once(self): source = self.tmpdir / 'source' source.mkdir() (source / 'foo.py').touch() (source / 'bar.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(str(source), str(target), main='pkg.mod:fn') with zipfile.ZipFile(str(target), 'r') as z: self.assertEqual(1, z.namelist().count('__main__.py'))
def run(self): with TemporaryDirectory() as tmpdir: copytree('.', os.path.join(tmpdir, 'css-html-js-minify')) fyle = os.path.join(tmpdir, '__main__.py') with open(fyle, 'w', encoding='utf-8') as entry: entry.write( "import runpy\nrunpy.run_module('css-html-js-minify')") create_archive(tmpdir, 'css-html-js-minify.pyz', '/usr/bin/env python3', "css-html-js-minify")
def test_remove_shebang(self): # Test that we can remove the shebang from a file. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(str(source), str(target), interpreter='python') new_target = self.tmpdir / 'changed.pyz' zipapp.create_archive(str(target), str(new_target), interpreter=None) self.assertEqual(zipapp.get_interpreter(str(new_target)), None)
def test_main_written(self): # Test that the __main__.py is written correctly. source = self.tmpdir / 'source' source.mkdir() (source / 'foo.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(str(source), str(target), main='pkg.mod:fn') with zipfile.ZipFile(str(target), 'r') as z: self.assertIn('__main__.py', z.namelist()) self.assertIn(b'pkg.mod.fn()', z.read('__main__.py'))
def test_custom_interpreter(self): # Test that a shebang line with a custom interpreter is written # correctly. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(str(source), str(target), interpreter='python') with target.open('rb') as f: self.assertEqual(f.read(2), b'#!') self.assertEqual(b'python\n', f.readline())
def test_write_shebang_to_fileobj(self): # Test that we can change the shebang of a file, writing the result to a # file object. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(str(source), str(target), interpreter='python') new_target = io.BytesIO() zipapp.create_archive(str(target), new_target, interpreter='python2.7') self.assertTrue(new_target.getvalue().startswith(b'#!python2.7\n'))
def test_read_from_pathobj(self): # Test that we can copy an archive using a pathlib.Path object # for the source. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target1 = self.tmpdir / 'target1.pyz' target2 = self.tmpdir / 'target2.pyz' zipapp.create_archive(source, target1, interpreter='python') zipapp.create_archive(target1, target2, interpreter='python2.7') self.assertEqual(zipapp.get_interpreter(target2), 'python2.7')
def get_package(self, name): # if isinstance(source, types.ModuleType): # source = os.path.dirname(source.__file__) if name: target = BytesIO() try: zipapp.create_archive('wheels/' + name, target=target) except zipapp.ZipAppError: pass else: # TODO: hash and cache? return target.getbuffer()
def test_read_from_fileobj(self): # Test that we can copy an archive using an open file object. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = self.tmpdir / 'source.pyz' temp_archive = io.BytesIO() zipapp.create_archive(str(source), temp_archive, interpreter='python') new_target = io.BytesIO() temp_archive.seek(0) zipapp.create_archive(temp_archive, new_target, interpreter='python2.7') self.assertTrue(new_target.getvalue().startswith(b'#!python2.7\n'))
def test_create_archive_with_compression(self): # Test packing a directory into a compressed archive. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() (source / 'test.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(source, target, compressed=True) with zipfile.ZipFile(target, 'r') as z: for name in ('__main__.py', 'test.py'): self.assertEqual(z.getinfo(name).compress_type, zipfile.ZIP_DEFLATED)
def test_main_validation(self): # Test that invalid values for main are rejected. source = self.tmpdir / 'source' source.mkdir() target = self.tmpdir / 'source.pyz' problems = [ '', 'foo', 'foo:', ':bar', '12:bar', 'a.b.c.:d', '.a:b', 'a:b.', 'a:.b', 'a:silly name' ] for main in problems: with self.subTest(main=main): with self.assertRaises(zipapp.ZipAppError): zipapp.create_archive(str(source), str(target), main=main)
def test_content_of_copied_archive(self): # Test that copying an archive doesn't corrupt it. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() target = io.BytesIO() zipapp.create_archive(str(source), target, interpreter='python') new_target = io.BytesIO() target.seek(0) zipapp.create_archive(target, new_target, interpreter=None) new_target.seek(0) with zipfile.ZipFile(new_target, 'r') as z: self.assertEqual(set(z.namelist()), {'__main__.py'})
def test_create_archive_with_subdirs(self): # Test packing a directory includes entries for subdirectories. source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() (source / 'foo').mkdir() (source / 'bar').mkdir() (source / 'foo' / '__init__.py').touch() target = io.BytesIO() zipapp.create_archive(str(source), target) target.seek(0) with zipfile.ZipFile(target, 'r') as z: self.assertIn('foo/', z.namelist()) self.assertIn('bar/', z.namelist())
def test_create_archive_with_include_file(self): # Test packing a directory and using include_file to specify which files to include. def skip_pyc_files(file): return '.pyc' not in str(file) source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() (source / 'test.py').touch() (source / 'test.pyc').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(source, target, include_file=skip_pyc_files) with zipfile.ZipFile(target, 'r') as z: self.assertIn('__main__.py', z.namelist()) self.assertIn('test.py', z.namelist()) self.assertNotIn('test.pyc', z.namelist())
def test_main_only_written_once(self): # Test that we don't write multiple __main__.py files. # The initial implementation had this bug; zip files allow # multiple entries with the same name source = self.tmpdir / 'source' source.mkdir() # Write 2 files, as the original bug wrote __main__.py # once for each file written :-( # See http://bugs.python.org/review/23491/diff/13982/Lib/zipapp.py#newcode67Lib/zipapp.py:67 # (line 67) (source / 'foo.py').touch() (source / 'bar.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(str(source), str(target), main='pkg.mod:fn') with zipfile.ZipFile(str(target), 'r') as z: self.assertEqual(1, z.namelist().count('__main__.py'))
def test_create_archive_with_filter(self): # Test packing a directory and using filter to specify # which files to include. def skip_pyc_files(path): return path.suffix != '.pyc' source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() (source / 'test.py').touch() (source / 'test.pyc').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(source, target, filter=skip_pyc_files) with zipfile.ZipFile(target, 'r') as z: self.assertIn('__main__.py', z.namelist()) self.assertIn('test.py', z.namelist()) self.assertNotIn('test.pyc', z.namelist())
def test_create_archive_filter_exclude_dir(self): # Test packing a directory and using a filter to exclude a # subdirectory (ensures that the path supplied to include # is relative to the source location, as expected). def skip_dummy_dir(path): return path.parts[0] != 'dummy' source = self.tmpdir / 'source' source.mkdir() (source / '__main__.py').touch() (source / 'test.py').touch() (source / 'dummy').mkdir() (source / 'dummy' / 'test2.py').touch() target = self.tmpdir / 'source.pyz' zipapp.create_archive(source, target, filter=skip_dummy_dir) with zipfile.ZipFile(target, 'r') as z: self.assertEqual(len(z.namelist()), 2) self.assertIn('__main__.py', z.namelist()) self.assertIn('test.py', z.namelist())
os.rename(os.path.join(sp, child), os.path.join(instdir, child)) if len(sys.argv) > 1: PYTHON = sys.argv[1] else: PYTHON = "/usr/bin/env python3" with tempfile.TemporaryDirectory() as instdir: generate_thrift_code(instdir) for src_dir, dest_prefix in MODULES: copy_py(os.path.join(OSS_DIR, src_dir), instdir, dest_prefix) for dep in DEPS: # There's no supported way to call `pip` in process, so we just # have to shell out and install it where we want it. run_cmd([sys.executable, "-m", "pip", "install", dep, "--prefix", instdir]) move_site_packages_to_root(instdir) # run_cmd(["find", instdir]) # Generate the `eden` executable zipfile. # We keep the shebang a little more flexible than just sys.executable to # minimize headaches if the system python is upgraded; there are no guarantees # that we'll keep running, but it seems more likely that we will than if we # hard coded it. zipapp.create_archive( instdir, target="eden.zip", interpreter=PYTHON, main="eden.cli.main:main" )