pypeline-runner 0.1.0__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.
File without changes
@@ -0,0 +1,43 @@
1
+ from pathlib import Path
2
+ from typing import List
3
+
4
+ from py_app_dev.core.exceptions import UserNotificationException
5
+ from py_app_dev.core.logging import logger
6
+
7
+ from ..domain.execution_context import ExecutionContext
8
+ from ..domain.pipeline import PipelineStep
9
+
10
+
11
+ class CreateVEnv(PipelineStep):
12
+ def __init__(self, execution_context: ExecutionContext, output_dir: Path) -> None:
13
+ super().__init__(execution_context, output_dir)
14
+ self.logger = logger.bind()
15
+ self.logger = logger.bind()
16
+
17
+ @property
18
+ def install_dirs(self) -> List[Path]:
19
+ return [self.project_root_dir / dir for dir in [".venv/Scripts", ".venv/bin"] if (self.project_root_dir / dir).exists()]
20
+
21
+ def get_name(self) -> str:
22
+ return self.__class__.__name__
23
+
24
+ def run(self) -> int:
25
+ self.logger.debug(f"Run {self.get_name()} step. Output dir: {self.output_dir}")
26
+ build_script_path = self.project_root_dir / "bootstrap.py"
27
+ if not build_script_path.exists():
28
+ raise UserNotificationException("Failed to find bootstrap script. Make sure that the project is initialized correctly.")
29
+ self.execution_context.create_process_executor(
30
+ ["python", build_script_path.as_posix()],
31
+ cwd=self.project_root_dir,
32
+ ).execute()
33
+ self.execution_context.add_install_dirs(self.install_dirs)
34
+ return 0
35
+
36
+ def get_inputs(self) -> List[Path]:
37
+ return []
38
+
39
+ def get_outputs(self) -> List[Path]:
40
+ return []
41
+
42
+ def update_execution_context(self) -> None:
43
+ pass
@@ -0,0 +1,87 @@
1
+ import io
2
+ import json
3
+ import traceback
4
+ from dataclasses import dataclass
5
+ from pathlib import Path
6
+ from typing import ClassVar, List
7
+
8
+ from mashumaro.config import TO_DICT_ADD_OMIT_NONE_FLAG, BaseConfig
9
+ from mashumaro.mixins.json import DataClassJSONMixin
10
+ from py_app_dev.core.exceptions import UserNotificationException
11
+ from py_app_dev.core.logging import logger
12
+ from py_app_dev.core.scoop_wrapper import ScoopWrapper
13
+
14
+ from ..domain.execution_context import ExecutionContext
15
+ from ..domain.pipeline import PipelineStep
16
+
17
+
18
+ @dataclass
19
+ class ScoopInstallExecutionInfo(DataClassJSONMixin):
20
+ install_dirs: List[Path]
21
+
22
+ class Config(BaseConfig):
23
+ """Base configuration for JSON serialization with omitted None values."""
24
+
25
+ code_generation_options: ClassVar[List[str]] = [TO_DICT_ADD_OMIT_NONE_FLAG]
26
+
27
+ @classmethod
28
+ def from_json_file(cls, file_path: Path) -> "ScoopInstallExecutionInfo":
29
+ try:
30
+ result = cls.from_dict(json.loads(file_path.read_text()))
31
+ except Exception as e:
32
+ output = io.StringIO()
33
+ traceback.print_exc(file=output)
34
+ raise UserNotificationException(output.getvalue()) from e
35
+ return result
36
+
37
+ def to_json_string(self) -> str:
38
+ return json.dumps(self.to_dict(omit_none=True), indent=2)
39
+
40
+ def to_json_file(self, file_path: Path) -> None:
41
+ file_path.write_text(self.to_json_string())
42
+
43
+
44
+ def create_scoop_wrapper() -> ScoopWrapper:
45
+ return ScoopWrapper()
46
+
47
+
48
+ class ScoopInstall(PipelineStep):
49
+ def __init__(self, execution_context: ExecutionContext, output_dir: Path) -> None:
50
+ super().__init__(execution_context, output_dir)
51
+ self.logger = logger.bind()
52
+ self.execution_info = ScoopInstallExecutionInfo([])
53
+ # One needs to keep track of the installed apps to get the required paths
54
+ # even if the step does not need to run.
55
+ self.execution_info_file = self.output_dir.joinpath("scoop_install_exec_info.json")
56
+
57
+ def get_name(self) -> str:
58
+ return self.__class__.__name__
59
+
60
+ @property
61
+ def install_dirs(self) -> List[Path]:
62
+ return self.execution_info.install_dirs
63
+
64
+ @property
65
+ def scoop_file(self) -> Path:
66
+ return self.project_root_dir.joinpath("scoopfile.json")
67
+
68
+ def run(self) -> int:
69
+ self.logger.debug(f"Run {self.get_name()} step. Output dir: {self.output_dir}")
70
+ installed_apps = create_scoop_wrapper().install(self.scoop_file)
71
+ for app in installed_apps:
72
+ self.install_dirs.extend(app.get_all_required_paths())
73
+ self.execution_info.to_json_file(self.execution_info_file)
74
+ return 0
75
+
76
+ def get_inputs(self) -> List[Path]:
77
+ return [self.scoop_file]
78
+
79
+ def get_outputs(self) -> List[Path]:
80
+ return self.install_dirs
81
+
82
+ def update_execution_context(self) -> None:
83
+ install_dirs = ScoopInstallExecutionInfo.from_json_file(self.execution_info_file).install_dirs
84
+ # Make the list unique and keep the order
85
+ unique_paths = list(dict.fromkeys(install_dirs))
86
+ # Update the install directories for the subsequent steps
87
+ self.execution_context.add_install_dirs(unique_paths)
@@ -0,0 +1,54 @@
1
+ from pathlib import Path
2
+ from typing import List
3
+
4
+ from py_app_dev.core.exceptions import UserNotificationException
5
+ from py_app_dev.core.logging import logger
6
+
7
+ from ..domain.execution_context import ExecutionContext
8
+ from ..domain.pipeline import PipelineStep
9
+
10
+
11
+ class WestInstall(PipelineStep):
12
+ def __init__(self, execution_context: ExecutionContext, output_dir: Path) -> None:
13
+ super().__init__(execution_context, output_dir)
14
+ self.logger = logger.bind()
15
+ self.artifacts_locator = execution_context.create_artifacts_locator()
16
+
17
+ def get_name(self) -> str:
18
+ return self.__class__.__name__
19
+
20
+ @property
21
+ def west_manifest_file(self) -> Path:
22
+ return self.project_root_dir.joinpath("west.yaml")
23
+
24
+ def run(self) -> int:
25
+ self.logger.debug(f"Run {self.get_name()} step. Output dir: {self.output_dir}")
26
+ try:
27
+ self.execution_context.create_process_executor(
28
+ [
29
+ "west",
30
+ "init",
31
+ "-l",
32
+ "--mf",
33
+ self.west_manifest_file.as_posix(),
34
+ self.artifacts_locator.build_dir.joinpath("west").as_posix(),
35
+ ],
36
+ cwd=self.project_root_dir,
37
+ ).execute()
38
+ self.execution_context.create_process_executor(
39
+ ["west", "update"],
40
+ cwd=self.artifacts_locator.build_dir,
41
+ ).execute()
42
+ except Exception as e:
43
+ raise UserNotificationException(f"Failed to initialize and update with west: {e}") from e
44
+
45
+ return 0
46
+
47
+ def get_inputs(self) -> List[Path]:
48
+ return [self.west_manifest_file]
49
+
50
+ def get_outputs(self) -> List[Path]:
51
+ return []
52
+
53
+ def update_execution_context(self) -> None:
54
+ pass
@@ -0,0 +1,22 @@
1
+
2
+ MIT License
3
+
4
+ Copyright (c) 2024 cuinixam
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
@@ -0,0 +1,120 @@
1
+ Metadata-Version: 2.1
2
+ Name: pypeline-runner
3
+ Version: 0.1.0
4
+ Summary: Configure and execute pipelines with Python (similar to GitHub workflows or Jenkins pipelines).
5
+ Home-page: https://github.com/cuinixam/pypeline
6
+ License: MIT
7
+ Author: cuinixam
8
+ Author-email: me@cuinixam.com
9
+ Requires-Python: >=3.10,<4.0
10
+ Classifier: Development Status :: 2 - Pre-Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Natural Language :: English
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Software Development :: Libraries
20
+ Requires-Dist: py-app-dev (>=2.1.0,<3.0.0)
21
+ Requires-Dist: typer[all] (>=0.12.0,<0.13.0)
22
+ Project-URL: Bug Tracker, https://github.com/cuinixam/pypeline/issues
23
+ Project-URL: Changelog, https://github.com/cuinixam/pypeline/blob/main/CHANGELOG.md
24
+ Project-URL: Documentation, https://pypeline-runner.readthedocs.io
25
+ Project-URL: Repository, https://github.com/cuinixam/pypeline
26
+ Description-Content-Type: text/markdown
27
+
28
+ # Python Pipeline
29
+
30
+ <p align="center">
31
+ <a href="https://github.com/cuinixam/pypeline/actions/workflows/ci.yml?query=branch%3Amain">
32
+ <img src="https://img.shields.io/github/actions/workflow/status/cuinixam/pypeline/ci.yml?branch=main&label=CI&logo=github&style=flat-square" alt="CI Status" >
33
+ </a>
34
+ <a href="https://pypeline.readthedocs.io">
35
+ <img src="https://img.shields.io/readthedocs/pypeline.svg?logo=read-the-docs&logoColor=fff&style=flat-square" alt="Documentation Status">
36
+ </a>
37
+ <a href="https://codecov.io/gh/cuinixam/pypeline">
38
+ <img src="https://img.shields.io/codecov/c/github/cuinixam/pypeline.svg?logo=codecov&logoColor=fff&style=flat-square" alt="Test coverage percentage">
39
+ </a>
40
+ </p>
41
+ <p align="center">
42
+ <a href="https://python-poetry.org/">
43
+ <img src="https://img.shields.io/badge/packaging-poetry-299bd7?style=flat-square&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAASCAYAAABrXO8xAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAJJSURBVHgBfZLPa1NBEMe/s7tNXoxW1KJQKaUHkXhQvHgW6UHQQ09CBS/6V3hKc/AP8CqCrUcpmop3Cx48eDB4yEECjVQrlZb80CRN8t6OM/teagVxYZi38+Yz853dJbzoMV3MM8cJUcLMSUKIE8AzQ2PieZzFxEJOHMOgMQQ+dUgSAckNXhapU/NMhDSWLs1B24A8sO1xrN4NECkcAC9ASkiIJc6k5TRiUDPhnyMMdhKc+Zx19l6SgyeW76BEONY9exVQMzKExGKwwPsCzza7KGSSWRWEQhyEaDXp6ZHEr416ygbiKYOd7TEWvvcQIeusHYMJGhTwF9y7sGnSwaWyFAiyoxzqW0PM/RjghPxF2pWReAowTEXnDh0xgcLs8l2YQmOrj3N7ByiqEoH0cARs4u78WgAVkoEDIDoOi3AkcLOHU60RIg5wC4ZuTC7FaHKQm8Hq1fQuSOBvX/sodmNJSB5geaF5CPIkUeecdMxieoRO5jz9bheL6/tXjrwCyX/UYBUcjCaWHljx1xiX6z9xEjkYAzbGVnB8pvLmyXm9ep+W8CmsSHQQY77Zx1zboxAV0w7ybMhQmfqdmmw3nEp1I0Z+FGO6M8LZdoyZnuzzBdjISicKRnpxzI9fPb+0oYXsNdyi+d3h9bm9MWYHFtPeIZfLwzmFDKy1ai3p+PDls1Llz4yyFpferxjnyjJDSEy9CaCx5m2cJPerq6Xm34eTrZt3PqxYO1XOwDYZrFlH1fWnpU38Y9HRze3lj0vOujZcXKuuXm3jP+s3KbZVra7y2EAAAAAASUVORK5CYII=" alt="Poetry">
44
+ </a>
45
+ <a href="https://github.com/astral-sh/ruff">
46
+ <img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="ruff">
47
+ </a>
48
+ <a href="https://github.com/pre-commit/pre-commit">
49
+ <img src="https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=flat-square" alt="pre-commit">
50
+ </a>
51
+ </p>
52
+ <p align="center">
53
+ <a href="https://pypi.org/project/pypeline/">
54
+ <img src="https://img.shields.io/pypi/v/pypeline.svg?logo=python&logoColor=fff&style=flat-square" alt="PyPI Version">
55
+ </a>
56
+ <img src="https://img.shields.io/pypi/pyversions/pypeline.svg?style=flat-square&logo=python&amp;logoColor=fff" alt="Supported Python versions">
57
+ <img src="https://img.shields.io/pypi/l/pypeline.svg?style=flat-square" alt="License">
58
+ </p>
59
+
60
+ Configure and execute steps for developing a python package.
61
+
62
+ ## Installation
63
+
64
+ Install this via pip (or your favourite package manager):
65
+
66
+ `pip install pypeline`
67
+
68
+ ## Start developing
69
+
70
+ The project uses Poetry for dependencies management and packaging.
71
+ Run the `bootstrap.ps1` script to install Python and create the virtual environment.
72
+
73
+ ```powershell
74
+ .\bootstrap.ps1
75
+ ```
76
+
77
+ This will also generate a `poetry.lock` file, you should track this file in version control.
78
+
79
+ To execute the test suite, call pytest inside Poetry's virtual environment via `poetry run`:
80
+
81
+ ```shell
82
+ .venv/Scripts/poetry run pytest
83
+ ```
84
+
85
+ Check out the Poetry documentation for more information on the available commands.
86
+
87
+ For those using [VS Code](https://code.visualstudio.com/) there are tasks defined for the most common commands:
88
+
89
+ - bootstrap
90
+ - install dependencies
91
+ - run tests
92
+ - run all checks configured for pre-commit
93
+ - generate documentation
94
+
95
+ See the `.vscode/tasks.json` for more details.
96
+
97
+ ## Committing changes
98
+
99
+ This repository uses [commitlint](https://github.com/conventional-changelog/commitlint) for checking if the commit message meets the [conventional commit format](https://www.conventionalcommits.org/en).
100
+
101
+ ## Contributors ✨
102
+
103
+ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
104
+
105
+ <!-- prettier-ignore-start -->
106
+ <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
107
+ <!-- markdownlint-disable -->
108
+ <!-- markdownlint-enable -->
109
+ <!-- ALL-CONTRIBUTORS-LIST:END -->
110
+ <!-- prettier-ignore-end -->
111
+
112
+ This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
113
+
114
+ ## Credits
115
+
116
+ This package was created with
117
+ [Copier](https://copier.readthedocs.io/) and the
118
+ [cuinixam/pypackage-template](https://github.com/cuinixam/pypackage-template)
119
+ project template.
120
+
@@ -0,0 +1,30 @@
1
+ pypeline/__init__.py,sha256=kUR5RAFc7HCeiqdlX36dZOHkUI5wI6V_43RpEcD8b-0,22
2
+ pypeline/__run.py,sha256=TCdaX05Qm3g8T4QYryKB25Xxf0L5Km7hFOHe1mK9vI0,350
3
+ pypeline/domain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ pypeline/domain/artifacts.py,sha256=qXshnk9umi0AVGV4m5iEiy_MQ5Ad2LDZwI8OULU-qMk,1355
5
+ pypeline/domain/config.py,sha256=HpU-d_oHZYCCbc1Fer3BJwAma94eL97eXTtKZEsrVpQ,1491
6
+ pypeline/domain/execution_context.py,sha256=0zc3OgXeIMDpgWWYMaDGub7fY5urLLR79yuCaXVxoTQ,1101
7
+ pypeline/domain/pipeline.py,sha256=VzzYqi3WyDmXN3UblTrfcirmh2PXqrdt_Gfi1Qtkln0,817
8
+ pypeline/domain/project_slurper.py,sha256=YCho7V1BHjFmC_foxHFaWX8c_VbMJ16XEB4CQBlMrhc,894
9
+ pypeline/kickstart/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ pypeline/kickstart/create.py,sha256=iTf7I5POHTKXZ7RuZ6iVHsBT8D02Nws-h0ZH53Rk2cI,2410
11
+ pypeline/kickstart/templates/bootstrap/bootstrap.ps1,sha256=IcgNohR8Fllz234DXQOl4N59I38t0mZ0k6ziu3Uu2kA,5772
12
+ pypeline/kickstart/templates/bootstrap/bootstrap.py,sha256=9DstyqJFVcBHOs5cS2dU43FY7dLusid5KEi55TeaJwk,15971
13
+ pypeline/kickstart/templates/project/.gitignore,sha256=vX-IAjvkjxgNIYBQmqaRRhWRO2uONl0GR355PiQPjIk,13
14
+ pypeline/kickstart/templates/project/poetry.toml,sha256=q5gF2MWexTFIahJ6StUa3y62HDUrRW7t8kGFszZhgp4,34
15
+ pypeline/kickstart/templates/project/pypeline.yaml,sha256=i9YSqpS2o-_Bzl69fvdOFVyYRMsDCtDy8usBpk-hqnE,219
16
+ pypeline/kickstart/templates/project/pyproject.toml,sha256=nz0K93bcLW3zikxdg39Pl030VoXZiUj78mFfgAw0Fk8,202
17
+ pypeline/kickstart/templates/project/scoopfile.json,sha256=DcfZ8jYf9hmPHM-AWwnPKQJCzRG3fCuYtMeoY01nkag,219
18
+ pypeline/kickstart/templates/project/steps/my_step.py,sha256=YNRdb7ofqo3PxMQe8Vhtf7K9eZclv-6J0IwMrd3E70w,651
19
+ pypeline/main.py,sha256=f8SMN_RUU35lv7dNnBDIzrBOpe76YGuRS6ouJ1zkNlI,3365
20
+ pypeline/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
+ pypeline/pypeline.py,sha256=yZ4nIBtI7Yrz-d8rmslERdtwcJiBf1D9tpOHFR5iAvM,4235
22
+ pypeline/steps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
+ pypeline/steps/create_venv.py,sha256=HeoJYDdyGEOwFnK_9eYEK32l6F9MpEsYSiM91uLVt2o,1599
24
+ pypeline/steps/scoop_install.py,sha256=KozpYMG1qITo21u6cIf9USkjIp2gvZ3V2DMzhi8fVyg,3257
25
+ pypeline/steps/west_install.py,sha256=QUopdIJne6OFhaXNlbOYrOGDPmNy6kgqZfOiUWQN7xY,1860
26
+ pypeline_runner-0.1.0.dist-info/LICENSE,sha256=sKxdoqSmW9ezvPvt0ZGJbneyA0SBcm0GiqzTv2jN230,1066
27
+ pypeline_runner-0.1.0.dist-info/METADATA,sha256=Iu5SHcaY61DS-qKvDhwYLh9bkwGvAkwnE1mm-U7UCbo,5755
28
+ pypeline_runner-0.1.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
29
+ pypeline_runner-0.1.0.dist-info/entry_points.txt,sha256=pe1u0uuhPI_yeQ0KjEw6jK-EvQfPcZwBSajgbAdKz1o,47
30
+ pypeline_runner-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 1.9.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ pypeline=pypeline.main:main
3
+