Skip to content

Commit

Permalink
Add doc strings and remaining tests
Browse files Browse the repository at this point in the history
  • Loading branch information
lucashuy committed Sep 26, 2023
1 parent b6638bd commit 3971e64
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 38 deletions.
48 changes: 35 additions & 13 deletions aws_lambda_builders/workflows/python_pip/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,24 @@
Action to resolve Python dependencies using PIP
"""

import logging
from typing import Optional, Tuple

from aws_lambda_builders.actions import ActionFailedError, BaseAction, Purpose
from aws_lambda_builders.architecture import X86_64
from aws_lambda_builders.binary_path import BinaryPath
from aws_lambda_builders.exceptions import MisMatchRuntimeError, RuntimeValidatorError
from aws_lambda_builders.workflows.python_pip.exceptions import MissingPipError
from aws_lambda_builders.workflows.python_pip.packager import (
DependencyBuilder,
PackagerError,
PipRunner,
PythonPipDependencyBuilder,
SubprocessPip,
)
from aws_lambda_builders.workflows.python_pip.utils import OSUtils

from .exceptions import MissingPipError
from .packager import DependencyBuilder, PackagerError, PipRunner, PythonPipDependencyBuilder, SubprocessPip
LOG = logging.getLogger(__name__)


class PythonPipBuildAction(BaseAction):
Expand All @@ -33,13 +41,13 @@ def __init__(

self._os_utils = OSUtils()

def execute(self):
try:
pip, python_with_pip = self._find_runtime_with_pip()
python_path = self.binaries[self.LANGUAGE].binary_path = python_with_pip
except MissingPipError as ex:
raise ActionFailedError(str(ex))
pip_runner = PipRunner(python_exe=python_path, pip=pip)
def execute(self) -> None:
"""
Executes the build action for Python `pip` workflows.
"""
pip, python_with_pip = self._find_runtime_with_pip()
pip_runner = PipRunner(python_exe=python_with_pip, pip=pip)

dependency_builder = DependencyBuilder(
osutils=self._os_utils, pip_runner=pip_runner, runtime=self.runtime, architecture=self.architecture
)
Expand All @@ -61,9 +69,21 @@ def execute(self):
except PackagerError as ex:
raise ActionFailedError(str(ex))

def _find_runtime_with_pip(self) -> Tuple[str, str]:
def _find_runtime_with_pip(self) -> Tuple[SubprocessPip, str]:
"""
foo bar
Finds a Python runtime that also contains `pip`.
Returns
-------
Tuple[SubprocessPip, str]
Returns a tuple of the SubprocessPip object created from
a valid Python runtime and the runtime path itself
Raises
------
ActionFailedError
Raised if the method is not able to find a valid runtime
that has the correct Python and pip installed
"""
binary_object: Optional[BinaryPath] = self.binaries.get(self.LANGUAGE)

Expand All @@ -78,11 +98,13 @@ def _find_runtime_with_pip(self) -> Tuple[str, str]:
pip = SubprocessPip(osutils=self._os_utils, python_exe=valid_python_path)

return (pip, valid_python_path)
except (MissingPipError, MisMatchRuntimeError, RuntimeValidatorError):
except (MisMatchRuntimeError, RuntimeValidatorError):
# runtime and mismatch exceptions should have been caught
# during the init phase

# we can ignore these and let the action fail at the end
pass
LOG.debug(f"Python runtime path '{valid_python_path}' does not match the workflow")
except MissingPipError:
LOG.debug(f"Python runtime path '{valid_python_path}' does not contain pip")

raise ActionFailedError("Failed to find a Python runtime containing pip on the PATH.")
86 changes: 61 additions & 25 deletions tests/unit/workflows/python_pip/test_actions.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import sys

from unittest import TestCase
from unittest.mock import MagicMock, patch, Mock, ANY
from unittest.mock import patch, Mock, ANY

from aws_lambda_builders.actions import ActionFailedError
from aws_lambda_builders.architecture import ARM64, X86_64
from aws_lambda_builders.binary_path import BinaryPath

from aws_lambda_builders.workflows.python_pip.actions import PythonPipBuildAction
from aws_lambda_builders.workflows.python_pip.exceptions import MissingPipError
from aws_lambda_builders.workflows.python_pip.packager import PackagerError
from aws_lambda_builders.workflows.python_pip.packager import PackagerError, SubprocessPip


class TestPythonPipBuildAction(TestCase):
Expand Down Expand Up @@ -81,24 +81,6 @@ def test_must_raise_exception_on_failure(self, find_runtime_mock, pip_dependency
with self.assertRaises(ActionFailedError):
action.execute()

# @patch("aws_lambda_builders.workflows.python_pip.actions.SubprocessPip")
# @patch("aws_lambda_builders.workflows.python_pip.actions.PythonPipBuildAction._find_runtime_with_pip")
# def test_must_raise_exception_on_pip_failure(self, find_runtime_mock, pip_sub_process_mock):
# pip_sub_process_mock.side_effect = MissingPipError(python_path="mockpath")
# find_runtime_mock.return_value = (Mock(), Mock())

# action = PythonPipBuildAction(
# "artifacts",
# "scratch_dir",
# "manifest",
# "runtime",
# None,
# {"python": BinaryPath(resolver=Mock(), validator=Mock(), binary="python", binary_path=sys.executable)},
# )

# with self.assertRaises(ActionFailedError):
# action.execute()

@patch("aws_lambda_builders.workflows.python_pip.actions.PythonPipDependencyBuilder")
@patch("aws_lambda_builders.workflows.python_pip.actions.PythonPipBuildAction._find_runtime_with_pip")
def test_action_must_call_builder_with_dependencies_dir(self, find_runtime_mock, pip_dependency_builder_mock):
Expand Down Expand Up @@ -130,7 +112,7 @@ def test_find_runtime_missing_binary_object(self):
def test_find_runtime_empty_exec_paths(self):
mock_resolver = Mock()
mock_resolver.resolver = Mock()
mock_resolver.resolver.exec_paths = {}
mock_resolver.resolver.exec_paths = []

mock_binaries = Mock()
mock_binaries.get = Mock(return_value=mock_resolver)
Expand All @@ -140,8 +122,62 @@ def test_find_runtime_empty_exec_paths(self):

self.assertEqual(str(ex.exception), "Failed to fetch Python binaries from the PATH.")

def test_find_runtime_found_pip(self):
pass
@patch("aws_lambda_builders.workflows.python_pip.actions.SubprocessPip")
def test_find_runtime_found_pip(self, pip_subprocess_mock):
expected_pip = Mock()
pip_subprocess_mock.return_value = expected_pip

expected_python_path = "my_python_path"

mock_binary_path = Mock()
mock_binary_path.resolver = Mock()
mock_binary_path.resolver.exec_paths = [expected_python_path]
mock_binary_path.validator = Mock()
mock_binary_path.validator.validate.return_value = expected_python_path

mock_binaries = Mock()
mock_binaries.get = Mock(return_value=mock_binary_path)

pip, runtime_path = PythonPipBuildAction(
Mock(), Mock(), Mock(), Mock(), Mock(), mock_binaries
)._find_runtime_with_pip()

self.assertEqual(pip, expected_pip)
self.assertEqual(runtime_path, expected_python_path)

@patch("aws_lambda_builders.workflows.python_pip.actions.SubprocessPip")
def test_find_runtime_no_pip_matches(self, pip_subprocess_mock):
python_path = "my_python_path"

pip_subprocess_mock.side_effect = [MissingPipError(python_path="message")]

mock_binary_path = Mock()
mock_binary_path.resolver = Mock()
mock_binary_path.resolver.exec_paths = [python_path]
mock_binary_path.validator = Mock()
mock_binary_path.validator.validate.return_value = python_path

mock_binaries = Mock()
mock_binaries.get = Mock(return_value=mock_binary_path)

with self.assertRaises(ActionFailedError) as ex:
PythonPipBuildAction(Mock(), Mock(), Mock(), Mock(), Mock(), mock_binaries)._find_runtime_with_pip()

self.assertEqual(str(ex.exception), "Failed to find a Python runtime containing pip on the PATH.")

def test_find_runtime_no_python_matches(self):
python_path = "my_python_path"

mock_binary_path = Mock()
mock_binary_path.resolver = Mock()
mock_binary_path.resolver.exec_paths = [python_path]
mock_binary_path.validator = Mock()
mock_binary_path.validator.validate.return_value = None

mock_binaries = Mock()
mock_binaries.get = Mock(return_value=mock_binary_path)

with self.assertRaises(ActionFailedError) as ex:
PythonPipBuildAction(Mock(), Mock(), Mock(), Mock(), Mock(), mock_binaries)._find_runtime_with_pip()

def test_find_runtime_no_matches(self):
pass
self.assertEqual(str(ex.exception), "Failed to find a Python runtime containing pip on the PATH.")

0 comments on commit 3971e64

Please sign in to comment.