spl-core 4.0.0__py3-none-any.whl → 4.1.1__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.
spl_core/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "4.0.0"
1
+ __version__ = "4.1.1"
@@ -0,0 +1,52 @@
1
+ import subprocess
2
+ from pathlib import Path
3
+ from typing import Dict, List, Optional
4
+
5
+
6
+ class CommandLineExecutor:
7
+ def __init__(
8
+ self,
9
+ cwd: Optional[Path] = None,
10
+ env: Optional[Dict[str, str]] = None,
11
+ ):
12
+ """
13
+ A class for executing command line commands.
14
+
15
+ Args:
16
+ - cmd: A string or list of strings representing the command to be executed.
17
+ - cwd: An optional Path object representing the current working directory.
18
+ - env: An optional dictionary of environment variables to be used in the command execution.
19
+ """
20
+ self.current_working_directory = cwd
21
+ self.env = env
22
+
23
+ def execute(self, cmd: str | List[str]) -> subprocess.CompletedProcess[str]:
24
+ """
25
+ Executes the command and returns a CompletedProcess object.
26
+
27
+ Returns:
28
+ - A subprocess.CompletedProcess object representing the result of the command execution.
29
+ """
30
+ command = " ".join([cmd] if isinstance(cmd, str) else cmd)
31
+ output = ""
32
+ try:
33
+ print(f"Running command: {command}")
34
+ with subprocess.Popen(
35
+ command,
36
+ cwd=str(self.current_working_directory or Path.cwd()),
37
+ stdout=subprocess.PIPE,
38
+ stderr=subprocess.STDOUT,
39
+ bufsize=1,
40
+ text=True,
41
+ env=self.env,
42
+ universal_newlines=True,
43
+ ) as process:
44
+ if process.stdout:
45
+ for line in process.stdout:
46
+ print(line, end="")
47
+ # We have to store the stdout content.
48
+ # This is necessary because the stdout object is closed after we printed its content
49
+ output += line
50
+ except Exception:
51
+ raise RuntimeError(f"Command '{command}' failed.") # noqa: B904
52
+ return subprocess.CompletedProcess(args=command, returncode=process.returncode, stdout=output, stderr=None)
@@ -4,10 +4,7 @@ verify_ssl = true
4
4
  name = "pypi"
5
5
 
6
6
  [packages]
7
- cookiecutter = "*"
8
- gcovr = "*"
9
- hammocking = "*"
10
- kconfiglib = "*"
7
+ spl-core = "*"
11
8
  jinja2 = "*"
12
9
  pytest = "*"
13
10
  pytest-env = "*"
@@ -0,0 +1,67 @@
1
+ import re
2
+ from abc import ABC, abstractmethod
3
+ from pathlib import Path
4
+ from typing import List
5
+
6
+ from spl_core.test_utils.spl_build import SplBuild
7
+
8
+
9
+ class BaseVariantTestRunner(ABC):
10
+ @property
11
+ def variant(self) -> str:
12
+ return re.sub(r"^Test_", "", self.__class__.__name__).replace("__", "/")
13
+
14
+ @property
15
+ @abstractmethod
16
+ def component_paths(self) -> List[Path]:
17
+ pass
18
+
19
+ @property
20
+ @abstractmethod
21
+ def expected_build_artifacts(self) -> List[Path]:
22
+ pass
23
+
24
+ @property
25
+ def expected_test_artifacts(self) -> List[Path]:
26
+ return [Path("reports/coverage/index.html")]
27
+
28
+ @property
29
+ def expected_variant_report_artifacts(self) -> List[Path]:
30
+ return [Path("reports/html/index.html")]
31
+
32
+ @property
33
+ def expected_component_report_artifacts(self) -> List[Path]:
34
+ return [
35
+ Path("coverage.html"),
36
+ Path("unit_test_results.html"),
37
+ Path("unit_test_spec.html"),
38
+ Path("doxygen/html/index.html"),
39
+ Path("coverage/index.html"),
40
+ ]
41
+
42
+ def assert_artifact_exists(self, dir: Path, artifact: Path) -> None:
43
+ if artifact.is_absolute():
44
+ assert artifact.exists(), f"Artifact {artifact} does not exist" # noqa: S101
45
+ else:
46
+ assert Path.joinpath(dir, artifact).exists(), f"Artifact {Path.joinpath(dir, artifact)} does not exist" # noqa: S101
47
+
48
+ def test_build(self) -> None:
49
+ spl_build: SplBuild = SplBuild(variant=self.variant, build_kit="prod")
50
+ assert 0 == spl_build.execute(target="all") # noqa: S101
51
+ for artifact in self.expected_build_artifacts:
52
+ self.assert_artifact_exists(dir=spl_build.build_dir, artifact=artifact)
53
+
54
+ def test_unittest(self) -> None:
55
+ spl_build: SplBuild = SplBuild(variant=self.variant, build_kit="test")
56
+ assert 0 == spl_build.execute(target="unittests") # noqa: S101
57
+ for artifact in self.expected_test_artifacts:
58
+ self.assert_artifact_exists(dir=spl_build.build_dir, artifact=artifact)
59
+
60
+ def test_reports(self) -> None:
61
+ spl_build: SplBuild = SplBuild(variant=self.variant, build_kit="test")
62
+ assert 0 == spl_build.execute(target="all") # noqa: S101
63
+ for artifact in self.expected_variant_report_artifacts:
64
+ self.assert_artifact_exists(dir=spl_build.build_dir, artifact=artifact)
65
+ for component in self.component_paths:
66
+ for artifact in self.expected_component_report_artifacts:
67
+ self.assert_artifact_exists(dir=Path.joinpath(spl_build.build_dir, "reports", "html", spl_build.build_dir, component, "reports"), artifact=artifact)
@@ -0,0 +1,77 @@
1
+ import time
2
+ from pathlib import Path
3
+ from typing import List, Optional
4
+
5
+ from py_app_dev.core.logging import time_it
6
+
7
+ from spl_core.common.command_line_executor import CommandLineExecutor
8
+
9
+
10
+ class SplBuild:
11
+ """Class for building an SPL repository."""
12
+
13
+ def __init__(self, variant: str, build_kit: str):
14
+ """
15
+ Initialize a SplBuild instance.
16
+
17
+ Args:
18
+ variant (str): The build variant.
19
+ build_kit (str): The build kit.
20
+
21
+ """
22
+ self.variant = variant
23
+ self.build_kit = build_kit
24
+
25
+ @property
26
+ def build_dir(self) -> Path:
27
+ """
28
+ Get the build directory.
29
+
30
+ Returns:
31
+ Path: The build directory path.
32
+
33
+ """
34
+ return Path(f"build/{self.variant}/{self.build_kit}")
35
+
36
+ @time_it()
37
+ def execute(self, target: str, additional_args: Optional[List[str]] = None) -> int:
38
+ """
39
+ Build the target
40
+
41
+ Args:
42
+ target (str): The build target.
43
+ additional_args (List[str], optional): Additional arguments for building. Defaults to ["-build"].
44
+
45
+ Returns:
46
+ int: 0 in case of success.
47
+
48
+ """
49
+ if additional_args is None:
50
+ additional_args = ["-build"]
51
+ return_code = -1
52
+ while True:
53
+ cmd = [
54
+ "build.bat",
55
+ "-buildKit",
56
+ self.build_kit,
57
+ "-variants",
58
+ self.variant,
59
+ "-target",
60
+ target,
61
+ "-reconfigure",
62
+ ]
63
+ cmd.extend(additional_args)
64
+ result = CommandLineExecutor().execute(cmd)
65
+ return_code = result.returncode
66
+ if result.returncode:
67
+ if result.stdout:
68
+ if any(error in str(result.stdout) for error in ["No valid floating license", "No valid license", "GHS_LMHOST = N/A"]):
69
+ print("Probably a license issue, retrying ...")
70
+ time.sleep(10)
71
+ else:
72
+ break
73
+ else:
74
+ break
75
+ else:
76
+ break
77
+ return return_code
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: spl-core
3
- Version: 4.0.0
3
+ Version: 4.1.1
4
4
  Summary: Software Product Line Support for CMake
5
5
  Home-page: https://github.com/avengineers/spl-core
6
6
  License: MIT
@@ -1,6 +1,7 @@
1
- spl_core/__init__.py,sha256=SQa6Ci17DORmGXi_wkOW9pPlUojF-qtjH6NV1WOThsU,22
1
+ spl_core/__init__.py,sha256=NtWqZUv_8plp1gndoYX_eAqe7K65oPMh-hIvB4Evdc8,22
2
2
  spl_core/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  spl_core/common/cmake.py,sha256=qId_QIGqvG_qkJWOTJjiW723nev6p0vvP3O0Jlfppz4,2054
4
+ spl_core/common/command_line_executor.py,sha256=2ck2ndExyjfFORGMHhtOPTWA3gJGJ_GdZfopen2ISoY,2019
4
5
  spl_core/common/path.py,sha256=sDujd3n4XP1XGjHc7ImXEdjihO6A8BOIDbKCf7HgQ0Y,462
5
6
  spl_core/gcov_maid/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
7
  spl_core/gcov_maid/gcov_maid.py,sha256=5rPIeL9daQDm5ad9xzaIhlDf_0H5g6r2zHo8WN8T4-8,1455
@@ -20,7 +21,7 @@ spl_core/project_creator/templates/project/{{cookiecutter.name}}/.vscode/tasks.j
20
21
  spl_core/project_creator/templates/project/{{cookiecutter.name}}/CMakeLists.txt,sha256=YHU4FBV3K4O3MUk289tLpC_t-rEAdbcXylWqNHRPVFY,1400
21
22
  spl_core/project_creator/templates/project/{{cookiecutter.name}}/KConfig,sha256=gqH4r2MYLLDtfUDQo2nYyx-rgHjBI62ca5U9TTlLFpc,598
22
23
  spl_core/project_creator/templates/project/{{cookiecutter.name}}/LICENSE,sha256=be3z6Wl8HeMABfG-fLSW2qst-PXlaByWyCbC6ztQT9A,1108
23
- spl_core/project_creator/templates/project/{{cookiecutter.name}}/Pipfile,sha256=6fajvqjqtuiWFcp0yFnseUNr_yJaKOx8bRUC7D4EKIg,563
24
+ spl_core/project_creator/templates/project/{{cookiecutter.name}}/Pipfile,sha256=Axw_VeFUvmaDzw2zKCbzv6ddzerOXy_eoVi-fFwm8Y8,513
24
25
  spl_core/project_creator/templates/project/{{cookiecutter.name}}/README.md,sha256=3-uBrhvLWhjaaJxKVQXc3kajwS2o49_snrQxw6V8kWM,337
25
26
  spl_core/project_creator/templates/project/{{cookiecutter.name}}/build.bat,sha256=HlOqePYRoHTrp7v6oQ551dXI-qCymGCG0gQ9Au6bpos,73
26
27
  spl_core/project_creator/templates/project/{{cookiecutter.name}}/build.ps1,sha256=37Eui885PQC62nOD6l4dEgaeXBntiVxLBy_NYWvWDzU,10528
@@ -59,7 +60,9 @@ spl_core/project_creator/templates/variant/{{cookiecutter.flavor}}/{{cookiecutte
59
60
  spl_core/project_creator/templates/variant/{{cookiecutter.flavor}}/{{cookiecutter.subsystem}}/parts.cmake,sha256=s-SMLPvajH4ZGupruSuh-SbL8jackverQpxGqdoD-Io,77
60
61
  spl_core/project_creator/variant.py,sha256=juZWBvLT7i1ZtP1LlGBDalzTf0mhFvfoON43VoqjZOA,532
61
62
  spl_core/project_creator/workspace_artifacts.py,sha256=E4oZjnFgC2-cz9jYIYUZzOC9R07LBJAbgGwHAuK0Arg,1279
62
- spl_core-4.0.0.dist-info/LICENSE,sha256=UjjA0o8f5tT3wVm7qodTLAhPWLl6kgVyn9FPAd1VeYY,1099
63
- spl_core-4.0.0.dist-info/METADATA,sha256=kTNj8t3EdkGLOxnG_apFFWSLKwPMWJ4lYl4Nji0rBBA,1997
64
- spl_core-4.0.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
65
- spl_core-4.0.0.dist-info/RECORD,,
63
+ spl_core/test_utils/base_variant_test_runner.py,sha256=FRPkyEyUVsFMmfshzooXzOPUeYaoMBQKFVi5m671P38,2665
64
+ spl_core/test_utils/spl_build.py,sha256=J7gj9Q979pivkYi6Bm2YUSCpjCXQ72rioCZbAgcCoLY,2172
65
+ spl_core-4.1.1.dist-info/LICENSE,sha256=UjjA0o8f5tT3wVm7qodTLAhPWLl6kgVyn9FPAd1VeYY,1099
66
+ spl_core-4.1.1.dist-info/METADATA,sha256=T0AkQPYgFf7UCpqGiAZqJ26AN_0l39OT7_qcbG9XKfg,1997
67
+ spl_core-4.1.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
68
+ spl_core-4.1.1.dist-info/RECORD,,