Skip to content

Commit

Permalink
chore: improve doc strings
Browse files Browse the repository at this point in the history
  • Loading branch information
tromai committed Dec 4, 2024
1 parent 0020c0d commit a43849b
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 38 deletions.
26 changes: 18 additions & 8 deletions scripts/release_scripts/run_macaron.sh
Original file line number Diff line number Diff line change
Expand Up @@ -468,26 +468,36 @@ if [[ -n "${python_venv_path:-}" ]]; then
mount_dir_ro "--python-venv" "$python_venv_path" "$python_venv_in_container"
fi

# Mount the local Maven repo into ${MACARON_WORKSPACE}/analyze_local_maven_repo_readonly.
# Mount the local Maven repo from the
# host file system into the container's
# ${MACARON_WORKSPACE}/analyze_local_maven_repo_readonly.
if [[ -n "${local_maven_repo:-}" ]]; then
local_maven_repo_in_container="${MACARON_WORKSPACE}/analyze_local_maven_repo_readonly"
argv_command+=("--local-maven-repo" "${MACARON_WORKSPACE}/analyze_local_maven_repo_readonly")

mount_dir_ro "--local-maven-repo" "$local_maven_repo" "$local_maven_repo_in_container"
else
# Perform default local maven repo when the user doesn't provide --local-maven-repo and `analyze` command is used.
# Mounting default local maven repo only
# when the user doesn't provide --local-maven-repo AND `analyze` command is used.
if [[ "$command" == "analyze" ]]; then
# We mount $HOME/.m2 into ${MACARON_WORKSPACE}/analyze_local_maven_repo_readonly ONLY IF $HOME/.m2 directory exists.
# We mount the host's $HOME/.m2 into the container's
# ${MACARON_WORKSPACE}/analyze_local_maven_repo_readonly ONLY IF $HOME/.m2 directory exists.
if [[ -d "$HOME/.m2" ]]; then
local_maven_repo_in_container="${MACARON_WORKSPACE}/analyze_local_maven_repo_readonly"
argv_command+=("--local-maven-repo" "${MACARON_WORKSPACE}/analyze_local_maven_repo_readonly")

mount_dir_ro "--local-maven-repo" "$HOME/.m2" "$local_maven_repo_in_container"
# If $HOME/.m2 doesn't exist, we create and mount an empty directory ${output}/analyze_local_maven_repo_readonly
# into ${MACARON_WORKSPACE}/analyze_local_maven_repo_readonly.
# This is because we don't want Macaron running within
# the container to use `$HOME/.m2` within the container as it is being used
# by the cyclonedx plugins for dependency resolution.
# If the host's $HOME/.m2 doesn't exist, we create and mount an empty directory ${output}/analyze_local_maven_repo_readonly
# into ${MACARON_WORKSPACE}/analyze_local_maven_repo_readonly. And then provide
# ${MACARON_WORKSPACE}/analyze_local_maven_repo_readonly into the --local-maven-repo
# flag.
# This is because:
# - By default if --local-maven-repo is not used, Macaron uses $HOME/.m2 of the current
# environment as the local maven repo.
# - If --local-maven-repo is not set when Macaron is running in the Docker container, it will try to
# use $HOME/.m2 WITHIN the container. This is not desirable as this $HOME/.m2 is being used
# by the cyclonedx plugins for dependency resolution, which requires read write. We treat the local
# maven repo as a read only directory, hence they cannot share.
else
local_maven_repo_in_container="${MACARON_WORKSPACE}/analyze_local_maven_repo_readonly"
output_local_maven_repo="${output}/analyze_local_maven_repo_readonly"
Expand Down
2 changes: 1 addition & 1 deletion src/macaron/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def analyze_slsa_levels_single(analyzer_single_args: argparse.Namespace) -> None
sys.exit(os.EX_OSFILE)
global_config.load_python_venv(analyzer_single_args.python_venv)

# Set Python virtual environment path.
# Set local maven repo path.
if analyzer_single_args.local_maven_repo is None:
# Load the default user local .m2 directory.
# Exit on error if $HOME is not set or empty.
Expand Down
118 changes: 96 additions & 22 deletions src/macaron/artifact/local_artifact.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,26 @@


def construct_local_artifact_paths_glob_pattern_maven_purl(maven_purl: PackageURL) -> list[str] | None:
"""Return a list of glob pattern(s) to be search in a maven layout local repo for artifact directories.
"""Return a list of glob pattern(s) representing maven artifacts in a local maven repository.
The glob pattern(s) can be used to search in `<...>/.m2/repository` directory.
Parameters
----------
maven_purl : PackageURL
A maven type PackageURL instance (e.g. `PackageURL.from_string("pkg:maven/com.oracle.macaron/[email protected])`)
A maven type PackageURL instance.
Returns
-------
list[str] | None
A list of glob patterns or None if an error happened.
Examples
--------
>>> from packageurl import PackageURL
>>> purl = PackageURL.from_string("pkg:maven/com.oracle.macaron/[email protected]")
>>> construct_local_artifact_paths_glob_pattern_maven_purl(purl)
['com/oracle/macaron/macaron/0.13.0']
"""
if not maven_purl.type == "maven":
return None
Expand All @@ -40,17 +49,27 @@ def construct_local_artifact_paths_glob_pattern_maven_purl(maven_purl: PackageUR


def construct_local_artifact_paths_glob_pattern_pypi_purl(pypi_purl: PackageURL) -> list[str] | None:
"""Return a list of glob pattern(s) to be search in a Python virtual environment for artifact directories.
"""Return a list of glob pattern(s) representing python artifacts in a virtual environment.
The glob pattern(s) can be used to search in `<...>/<python_venv>/lib/python3.x/site-packages`
directory.
Parameters
----------
maven_purl : PackageURL
A maven type PackageURL instance (e.g. `PackageURL.from_string("pkg:maven/com.oracle.macaron/[email protected])`)
A pypi type PackageURL instance.
Returns
-------
list[str] | None
A list of glob patterns or None if an error happened.
Examples
--------
>>> from packageurl import PackageURL
>>> purl = PackageURL.from_string("pkg:pypi/[email protected]")
>>> construct_local_artifact_paths_glob_pattern_pypi_purl(purl)
['django', 'django-1.11.1.dist-info', 'django-1.11.1.data']
"""
if not pypi_purl.type == "pypi":
return None
Expand All @@ -76,11 +95,21 @@ def find_artifact_paths_from_local_maven_repo(
local_maven_repo: str,
glob_patterns: list[str],
) -> list[str] | None:
"""Return a list of existed directories within `local_maven_repo`.
"""Find maven artifacts within a local maven repository directory.
Each directory path has the form ``local_maven_repo``/<artifact_specific_path>.
``local_maven_repo`` should be in format `<...>/.m2/repository`.
None means error.
Parameters
----------
local_maven_repo: str
The path to the directories to find artifacts.
glob_patterns: list[str]
The list of glob patterns that matches to artifact file names.
Returns
-------
list[str] | None
The list of path to found artifacts in the form of ``local_maven_repo``/<artifact_specific_path>
"""
if not os.path.isdir(local_maven_repo):
return None
Expand All @@ -100,15 +129,27 @@ def find_artifact_paths_from_local_maven_repo(
return artifact_paths


# Assume that local_python_venv exists.
# In here we need to do it case-insensitively
# We also assume that packages are just one level down from venv_path
# The return element are relative paths from venv.
def find_artifact_paths_from_python_venv(
venv_path: str,
glob_patterns: list[str],
) -> list[str] | None:
"""TBD."""
"""Find python artifacts within a python virtual environment directory.
For packages in the virtual environment, we will treat their name case-insensitively.
https://packaging.python.org/en/latest/specifications/name-normalization/
Parameters
----------
local_maven_repo: str
The path to the directories to find artifacts.
glob_patterns: list[str]
The list of glob patterns that matches to artifact file names.
Returns
-------
list[str] | None
The list of path to found artifacts in the form of ``local_maven_repo``/<artifact_specific_path>
"""
if not os.path.isdir(venv_path):
return None

Expand Down Expand Up @@ -139,7 +180,7 @@ def _get_local_artifact_path_for_build_tool_purl_type(
build_tool_purl_type: str,
local_artifact_repo: str,
) -> list[str] | None:
"""TBD."""
"""Find local artifacts within ``local_artifact_repo`` depending on the purl type."""
if build_tool_purl_type == "maven":
maven_artifact_patterns = construct_local_artifact_paths_glob_pattern_maven_purl(purl)
if not maven_artifact_patterns:
Expand Down Expand Up @@ -169,24 +210,57 @@ def _get_local_artifact_path_for_build_tool_purl_type(
return None


# key: purl type
# value: list of paths
# If a key doesn't exist -> cannot construct the artifact paths for that purl type
# (no local artifact repo found or not enough information from PURL type is not supported) OR no valid artifact paths found.
# We assume that the paths in local_artifact_repo_mapper all exists/
def get_local_artifact_paths(
purl: PackageURL,
build_tool_purl_types: list[str],
local_artifact_repo_mapper: Mapping[str, str],
) -> dict[str, list[str]]:
"""Get C."""
local_artifact_paths_purl_mapping = {}
"""Return the path to local artifacts for a PackageURL.
We look for local artifacts of this PURL in all local repos corresponding to each purl
type in ``build_tool_purl_types`` (e.g a pypi build tool type will map to the python virtual
environment, if available).
This function returns a dictionary with:
- keys: The purl type
- values: The list of aritfact paths corresponding to a purl type
If a key doesn't exist, we cannot construct the artifact paths for that purl type. This can
happen because of:
- no local artifact repo found or given from user OR
- not enough information from PURL type OR
- build PURL type is not supported OR
- no valid artifact paths found
We assume that all paths in ``local_artifact_repo_mapper`` exist.
Parameters
----------
purl : PackageURL
The purl we want to find local artifacts
build_tool_purl_types : list[str]
The list of build tool purl type to look for local artifacts.
local_artifact_repo_mapper: Mapping[str, str]
The mapping between each build purl type and the local artifact repo directory.
Returns
-------
dict[str, list[str]]
A mapping between build purl type and the paths to local artifacts if found.
"""
result = {}

for build_tool_purl_type in build_tool_purl_types:
local_artifact_repo = local_artifact_repo_mapper.get(build_tool_purl_type)
if not local_artifact_repo:
continue

# ``local_artifact_repo`` here correspond to ``build_tool_purl_type`` already
# However, because for each build tool purl type, we have different ways of:
# - Generating glob patterns
# - Applying the glob patterns
# I still put ``local_artifact_repo`` in _get_local_artifact_path_for_build_tool_purl_type
# to further handle those tasks.
artifact_paths = _get_local_artifact_path_for_build_tool_purl_type(
purl=purl,
build_tool_purl_type=build_tool_purl_type,
Expand All @@ -196,6 +270,6 @@ def get_local_artifact_paths(
if not artifact_paths:
continue

local_artifact_paths_purl_mapping[build_tool_purl_type] = artifact_paths
result[build_tool_purl_type] = artifact_paths

return local_artifact_paths_purl_mapping
return result
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def test_macaron_command_help() -> int:
return exit_code


def test_macaron_command_no_home_m2() -> int:
def test_macaron_command_no_home_m2_on_host() -> int:
"""Test if the ``macaron`` command in the container receives the correct arguments."""
test_cases = [
TestCase(
Expand All @@ -103,11 +103,11 @@ def test_macaron_command_no_home_m2() -> int:
return exit_code


def test_macaron_command_home_m2_available() -> int:
def test_macaron_command_host_home_m2_available() -> int:
"""Test if the ``macaron`` command in the container receives the correct arguments."""
test_cases = [
TestCase(
name="no --local-maven-repo and host $HOME/.m2 is available",
name="no --local-maven-repo provided by the user and host $HOME/.m2 is available",
script_args=["analyze"],
expected_macaron_args=["analyze", "--local-maven-repo", "/home/macaron/analyze_local_maven_repo_readonly"],
),
Expand All @@ -130,7 +130,7 @@ def test_macaron_command_home_m2_available() -> int:
return exit_code


def test_macaron_provide_local_maven_repo() -> int:
def test_macaron_user_provide_valid_local_maven_repo() -> int:
"""Test if the ``macaron`` command in the container receives the correct arguments."""
with tempfile.TemporaryDirectory() as temp_dir:
test_cases = [
Expand Down Expand Up @@ -159,9 +159,9 @@ def main() -> int:
"""Run all tests."""
return (
test_macaron_command_help()
| test_macaron_command_no_home_m2()
| test_macaron_command_home_m2_available()
| test_macaron_provide_local_maven_repo()
| test_macaron_command_no_home_m2_on_host()
| test_macaron_command_host_home_m2_available()
| test_macaron_user_provide_valid_local_maven_repo()
)


Expand Down

0 comments on commit a43849b

Please sign in to comment.