Skip to content

Commit

Permalink
Add python_compile function and update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
zackees committed Mar 25, 2024
1 parent 9c3c071 commit 912981d
Show file tree
Hide file tree
Showing 7 changed files with 137 additions and 81 deletions.
66 changes: 4 additions & 62 deletions src/python_compile/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,12 @@
"""

import argparse
import os
import sys
from dataclasses import dataclass
from pathlib import Path

from docker_run_cmd.api import docker_run
from python_compile.compile import DOCKER_FILE_MAP, Args, python_compile

from python_compile.native_build import run_native_build


@dataclass
class Args:
app_py: Path
requirements: Path | None = None
os: str | None = None


HERE = Path(__file__).parent
ASSETS = HERE / "assets"

DOCKER_FILE_MAP = {
"debian": ASSETS / "debian-dockerfile",
"windows": ASSETS
/ "windows-dockerfile", # Work in progress - cross compilation through fedora
"native": None,
}
CHOICES = list(DOCKER_FILE_MAP.keys())


def parse_args() -> argparse.Namespace:
Expand All @@ -38,7 +18,7 @@ def parse_args() -> argparse.Namespace:
"--os",
type=str,
help="Which os to use",
choices=DOCKER_FILE_MAP.keys(),
choices=CHOICES,
required=False,
)
parser.add_argument(
Expand All @@ -61,51 +41,13 @@ def parse_args() -> argparse.Namespace:
return parser.parse_args()


def run(args: Args) -> int:
"""Main entry point for the template_python_cmd package."""
os_system = args.os
app_py = args.app_py
requirements_txt = args.requirements
if os_system == "windows":
if os.name != "nt":
# Work in progress, compile windows apps from docker.
print("You must run this on a windows machine")
return 1
rtn = run_native_build(app_py=app_py, requirements_txt=requirements_txt)
return rtn
if os_system is None or os_system == "native":
rtn = run_native_build(app_py=app_py, requirements_txt=requirements_txt)
return rtn

dockerpath: Path | None = DOCKER_FILE_MAP.get(os_system)
if dockerpath is None:
print(f"OS {os_system} is not supported")
return 1
assert dockerpath.exists(), f"dockerpath {dockerpath} does not exist"
py_path = args.app_py
assert Path(py_path).as_posix(), "You must provide a python path"

extra_files: dict[Path, Path] = {}
if args.requirements:
extra_files[Path(args.requirements)] = Path("requirements.txt")

docker_run(
name=f"python-compile-{os_system}",
dockerfile_or_url=dockerpath,
cwd=os.getcwd(),
cmd_list=[py_path],
extra_files=extra_files,
)
return 0


def main() -> int:
cli_args = parse_args()
os_system = cli_args.os
app_py = cli_args.input
requirements_txt = cli_args.requirements
args = Args(app_py=app_py, requirements=requirements_txt, os=os_system)
return run(args)
return python_compile(args)


if __name__ == "__main__":
Expand Down
70 changes: 70 additions & 0 deletions src/python_compile/compile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"""
Main entry point.
"""

import os
from dataclasses import dataclass
from pathlib import Path

from docker_run_cmd.api import docker_run

from python_compile.native_build import run_native_build

HERE = Path(__file__).parent
ASSETS = HERE / "assets"

DOCKER_FILE_MAP = {
"debian": ASSETS / "debian-dockerfile",
"windows": ASSETS
/ "windows-dockerfile", # Work in progress - cross compilation through fedora
"native": None,
}


@dataclass
class Args:
app_py: Path
requirements: Path | None = None
os: str | None = None


HERE = Path(__file__).parent
ASSETS = HERE / "assets"


def python_compile(args: Args) -> int:
"""Main entry point for the template_python_cmd package."""
os_system = args.os
app_py = args.app_py
requirements_txt = args.requirements
if os_system == "windows":
if os.name != "nt":
# Work in progress, compile windows apps from docker.
print("You must run this on a windows machine")
return 1
rtn = run_native_build(app_py=app_py, requirements_txt=requirements_txt)
return rtn
if os_system is None or os_system == "native":
rtn = run_native_build(app_py=app_py, requirements_txt=requirements_txt)
return rtn

dockerpath: Path | None = DOCKER_FILE_MAP.get(os_system)
if dockerpath is None:
print(f"OS {os_system} is not supported")
return 1
assert dockerpath.exists(), f"dockerpath {dockerpath} does not exist"
py_path = args.app_py
assert Path(py_path).as_posix(), "You must provide a python path"

extra_files: dict[Path, Path] = {}
if args.requirements:
extra_files[Path(args.requirements)] = Path("requirements.txt")

docker_run(
name=f"python-compile-{os_system}",
dockerfile_or_url=dockerpath,
cwd=os.getcwd(),
cmd_list=[py_path],
extra_files=extra_files,
)
return 0
2 changes: 1 addition & 1 deletion test
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
set -e
. ./activate.sh
echo "Running unittests"
pytest -n auto -v tests
pytest -n 1 -v tests
19 changes: 12 additions & 7 deletions tests/test_cli_native.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
"""

import os
import shutil
import subprocess
import sys
import unittest
from pathlib import Path
from pprint import pprint
from tempfile import TemporaryDirectory

HERE = Path(__file__).parent
HERE = Path(__file__).parent.absolute()
PROJECT_ROOT = HERE.parent
DEMO_PY = PROJECT_ROOT / "src/python_compile/assets/demo_http_server.py"

Expand All @@ -21,23 +23,26 @@ def test_cli(self) -> None:
"""Test command line interface (CLI)."""
with TemporaryDirectory() as tmp_dir:
os.chdir(tmp_dir)
basename = DEMO_PY.name
shutil.copy(DEMO_PY, basename)
try:
cmd_list = [
"python-compile",
"--input",
str(DEMO_PY),
str(basename),
]
cmd_str = subprocess.list2cmdline(cmd_list)
print(f"Running: {cmd_str}")
rtn = os.system(" ".join(cmd_list))
self.assertEqual(0, rtn)
expected_path_gz: Path = Path("demo_http_server.bin.gz")
self.assertTrue(expected_path_gz.exists())

files = os.listdir()

pprint(files)
if sys.platform == "win32":
expected_path = Path("demo_http_server.exe")
self.assertTrue("demo_http_server.exe" in files)
else:
expected_path = Path("demo_http_server.bin")
self.assertTrue(expected_path.exists())
self.assertTrue("demo_http_server.bin.gz" in files)
finally:
os.chdir(PROJECT_ROOT)

Expand Down
31 changes: 31 additions & 0 deletions tests/test_debian.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,25 @@
"""

import os
import shutil
import subprocess
import unittest
from pathlib import Path
from pprint import pprint
from tempfile import TemporaryDirectory

from python_compile.cli import Args
from python_compile.compile import python_compile

HERE = Path(__file__).parent
PROJECT_ROOT = HERE.parent
DEMO_PY = PROJECT_ROOT / "src/python_compile/assets/demo_http_server.py"


class NativeTester(unittest.TestCase):
"""Main tester class."""

@unittest.skip("Skip test_compile")
def test_compile(self) -> None:
"""Test command line interface (CLI)."""
with TemporaryDirectory() as tmp_dir:
Expand All @@ -29,13 +39,34 @@ def test_compile(self) -> None:
print(f"Running: {cmd_str}")
rtn = os.system(" ".join(cmd_list))
self.assertEqual(0, rtn)
files = os.listdir(tmp_dir)
pprint(files)
expected_path_gz: Path = Path("demo_http_server.bin.gz")
self.assertTrue(expected_path_gz.exists())
expected_path = Path("demo_http_server.bin")
self.assertTrue(expected_path.exists())
finally:
os.chdir(prev_dir)

def test_compile_main(self) -> None:
"""Test command line interface (CLI)."""
with TemporaryDirectory() as tmp_dir:
prev_dir = os.getcwd()
os.chdir(tmp_dir)
try:
shutil.copy(DEMO_PY, DEMO_PY.name)
args = Args(app_py=Path(DEMO_PY.name), os="debian")
rtn = python_compile(args)
self.assertEqual(0, rtn)
files = os.listdir(tmp_dir)
pprint(files)
expected_path_gz: Path = Path("demo_http_server.bin.gz")
self.assertTrue(expected_path_gz.exists())
expected_path = Path("demo_http_server.bin.gz")
self.assertTrue(expected_path.exists())
finally:
os.chdir(prev_dir)


if __name__ == "__main__":
unittest.main()
14 changes: 9 additions & 5 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@
"""

import os
import shutil
import sys
import unittest
from pathlib import Path
from pprint import pprint
from tempfile import TemporaryDirectory

from python_compile.cli import Args, run
from python_compile.cli import Args
from python_compile.compile import python_compile

HERE = Path(__file__).parent
HERE = Path(__file__).parent.absolute()
PROJECT_ROOT = HERE.parent
DEMO_PY = PROJECT_ROOT / "src/python_compile/assets/demo_http_server.py"

Expand All @@ -24,13 +26,15 @@ def test_run_main(self) -> None:
with TemporaryDirectory(ignore_cleanup_errors=True) as tmp_dir:
prev_dir = os.getcwd()
os.chdir(tmp_dir)
basename = DEMO_PY.name
shutil.copy(DEMO_PY, basename)
if sys.platform == "win32":
expected_path = "demo_http_server.exe"
else:
expected_path = "demo_http_server.bin"
expected_path = "demo_http_server.bin.gz"
try:
args = Args(app_py=DEMO_PY)
rtn = run(args)
args = Args(app_py=Path(basename))
rtn = python_compile(args)
self.assertEqual(0, rtn)
files = os.listdir(tmp_dir)
pprint(files)
Expand Down
16 changes: 10 additions & 6 deletions tests/test_native.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@
"""

import os
import shutil
import subprocess
import sys
import unittest
from pathlib import Path
from tempfile import TemporaryDirectory

HERE = Path(__file__).parent.absolute()
PROJECT_ROOT = HERE.parent
DEMO_PY = PROJECT_ROOT / "src/python_compile/assets/demo_http_server.py"


class NativeTester(unittest.TestCase):
"""Main tester class."""
Expand All @@ -18,23 +23,22 @@ def test_compile(self) -> None:
with TemporaryDirectory() as tmp_dir:
prev_dir = os.getcwd()
os.chdir(tmp_dir)
basename = DEMO_PY.name
shutil.copy(DEMO_PY, basename)
try:
cmd_list = [
"python-compile",
"--input",
"src/python_compile/assets/demo_http_server.py",
basename,
]
cmd_str = subprocess.list2cmdline(cmd_list)
print(f"Running: {cmd_str}")
rtn = os.system(" ".join(cmd_list))
self.assertEqual(0, rtn)
expected_path_gz: Path = Path("demo_http_server.bin.gz")
self.assertTrue(expected_path_gz.exists())
if sys.platform == "win32":
expected_path = Path("demo_http_server.exe")
self.assertTrue("demo_http_server.exe" in os.listdir())
else:
expected_path = Path("demo_http_server.bin")
self.assertTrue(expected_path.exists())
self.assertTrue("demo_http_server.bin.gz" in os.listdir())
finally:
os.chdir(prev_dir)

Expand Down

0 comments on commit 912981d

Please sign in to comment.