nmk-workspace 1.0.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.
@@ -0,0 +1,27 @@
1
+ """
2
+ Python module for **nmk-workspace** plugin code.
3
+ """
4
+
5
+ from importlib.metadata import version
6
+
7
+ from nmk_base.version import VersionResolver
8
+
9
+ __title__ = "nmk-workspace"
10
+ try:
11
+ __version__ = version(__title__)
12
+ except Exception: # pragma: no cover
13
+ __version__ = "unknown"
14
+
15
+
16
+ class NmkWorkspaceVersionResolver(VersionResolver):
17
+ """
18
+ Version resolver for **${nmkWorkspacePluginVersion}**
19
+ """
20
+
21
+ def get_version(self) -> str:
22
+ """
23
+ Module version accessor
24
+
25
+ :return: current module version
26
+ """
27
+ return __version__
@@ -0,0 +1,82 @@
1
+ """
2
+ Nmk workspace plugin builders.
3
+ """
4
+
5
+ import fnmatch
6
+ import subprocess
7
+ from pathlib import Path
8
+ from typing import Union
9
+
10
+ from nmk.model.builder import NmkTaskBuilder
11
+
12
+
13
+ class SubProjectsBuilder(NmkTaskBuilder):
14
+ """
15
+ Builder for sub-projects in the workspace tree.
16
+
17
+ This builder is used to iterate on workspace sub-projects and trigger nmk build for each.
18
+ """
19
+
20
+ def build(
21
+ self,
22
+ root: str,
23
+ to_build_first: list[str],
24
+ to_build: list[str],
25
+ to_build_after: list[str],
26
+ excluded: list[str],
27
+ args: Union[list[str], str],
28
+ ignore_failures: bool = False,
29
+ ):
30
+ """
31
+ Build specified tasks for each sub-project.
32
+
33
+ :param root: Root path of the workspace
34
+ :param to_build_first: List of sub-projects paths to build first
35
+ :param to_build: List of sub-projects paths to build then
36
+ :param to_build_after: List of sub-projects paths to build after all the others
37
+ :param excluded: List of sub-projects glob patterns to exclude from building
38
+ :param args: List of nmk args to use for each sub-project
39
+ :param ignore_failures: Whether to ignore failure of sub-project builds
40
+ """
41
+
42
+ # Prepare args list
43
+ args_list = args if isinstance(args, list) else [a for a in args.split(" ") if a]
44
+
45
+ # Prepare global list of sub-projects to be built
46
+ sub_projects = []
47
+ sub_projects.extend(to_build_first)
48
+ sub_projects.extend([p for p in to_build if p not in to_build_after])
49
+ sub_projects.extend(to_build_after)
50
+
51
+ # Iterate on sub-projects
52
+ built_projects = set()
53
+ for sub_project in sub_projects:
54
+ # Handle duplicates
55
+ if sub_project in built_projects:
56
+ # Already done, skip
57
+ continue
58
+ built_projects.add(sub_project)
59
+
60
+ # Some log info...
61
+ self.logger.info(self.task.emoji, ">> ----------------------------------------------------------------")
62
+ self.logger.info(self.task.emoji, f">> Building sub-project: {sub_project}")
63
+ self.logger.info(self.task.emoji, ">> ----------------------------------------------------------------")
64
+
65
+ # Handle exclusions
66
+ if any(fnmatch.fnmatch(sub_project, pattern) for pattern in excluded):
67
+ self.logger.info(self.task.emoji, ">> skipped (excluded)")
68
+ continue
69
+
70
+ # Delegate build
71
+ sub_project_path = Path(root) / sub_project
72
+ nmk_args = ["nmk", "--log-prefix", f"{sub_project}/"] + args_list
73
+ self.logger.debug(">> Running command: " + " ".join(nmk_args))
74
+ cp = subprocess.run(nmk_args, cwd=sub_project_path)
75
+
76
+ # Handle build failure
77
+ if cp.returncode != 0:
78
+ error_msg = f"!! Failed to build sub-project: {sub_project} !!"
79
+ if ignore_failures:
80
+ self.logger.error(error_msg)
81
+ else:
82
+ raise RuntimeError(error_msg)
@@ -0,0 +1,17 @@
1
+ # Workspace plugin definition
2
+ refs:
3
+ - pip://nmk-base!plugin.yml
4
+ - subprojects.yml
5
+
6
+ config:
7
+ # Plugin version
8
+ nmkWorkspacePluginVersion:
9
+ __resolver__: nmk_workspace.NmkWorkspaceVersionResolver
10
+
11
+ # Plugin versions dict
12
+ nmkPluginsVersions:
13
+ nmk-workspace: ${nmkWorkspacePluginVersion}
14
+
15
+ # Plugin help links dict
16
+ nmkPluginsDocs:
17
+ nmk-workspace: https://nmk-workspace.readthedocs.io/
@@ -0,0 +1,42 @@
1
+ """
2
+ Nmk workspace plugin config item resolvers.
3
+ """
4
+
5
+ from pathlib import Path
6
+
7
+ from nmk.logs import NmkLogger
8
+ from nmk.model.resolver import NmkListConfigResolver
9
+ from nmk.utils import run_with_logs
10
+
11
+
12
+ class SubProjectsResolver(NmkListConfigResolver):
13
+ """
14
+ Resolver usable find sub-projects in the workspace tree.
15
+
16
+ Default behavior is to look sub-projects by iterating through git submodules.
17
+ (other behaviors may be implemented if needed later).
18
+ """
19
+
20
+ def get_value(self, name: str, root: str) -> list[str]:
21
+ """
22
+ Resolver for sub-projects list.
23
+
24
+ :root: root path of the workspace
25
+ :return: list of sub-projects paths relative to the workspace root
26
+ """
27
+
28
+ # Ask git for submodules paths
29
+ root_path = Path(root)
30
+ cp = run_with_logs(
31
+ ["git", "submodule", "foreach", "--quiet", "--recursive", "echo $sm_path"], cwd=root_path
32
+ ) # Note that $sm_path is a git variable, meaning this syntax is supported both on Linux and Windows
33
+ nmk_models = []
34
+ for candidate in cp.stdout.splitlines(keepends=False):
35
+ # Only keep ones with a default nmk model file
36
+ sub_project_path = candidate.strip()
37
+ candidate_path = root_path / sub_project_path / "nmk.yml"
38
+ if candidate_path.is_file():
39
+ nmk_models.append(sub_project_path)
40
+ else:
41
+ NmkLogger.debug(f"Sub-project {sub_project_path} does not have a default nmk model file, skipping it.")
42
+ return nmk_models
@@ -0,0 +1,119 @@
1
+ config:
2
+ # nmk subprojects found in git submodules
3
+ workspaceSubProjects:
4
+ __resolver__: nmk_workspace.resolvers.SubProjectsResolver
5
+ params:
6
+ root: ${PROJECTDIR}
7
+
8
+ # Ordered list of subprojects to build first
9
+ workspaceSubProjectsToBuildFirst: []
10
+
11
+ # Ordered list of subprojects to build after the other subprojects
12
+ workspaceSubProjectsToBuildAfter: []
13
+
14
+ # Detected list of subprojects to build
15
+ workspaceSubProjectsToBuild:
16
+ - ${workspaceSubProjects}
17
+
18
+ # Custom list of subprojects to be excluded from build
19
+ workspaceSubProjectsToExclude: []
20
+
21
+ # Extra args to be applied to all commands
22
+ workspaceBuildExtraArgs: ""
23
+
24
+ # Enabling options per task
25
+ workspaceBuildEnabled:
26
+ clean: true
27
+ setup: true
28
+ build: true
29
+ tests: true
30
+ package: true
31
+
32
+ # Ignore failures options per task
33
+ workspaceBuildIgnoreFailures:
34
+ clean: false
35
+ setup: false
36
+ build: false
37
+ tests: true
38
+ package: false
39
+
40
+ tasks:
41
+ # Workspace clean
42
+ workspace.clean:
43
+ description: Clean workspace projects
44
+ emoji: ":books:.:broom:"
45
+ builder: nmk_workspace.builders.SubProjectsBuilder
46
+ if: ${workspaceBuildEnabled.clean}
47
+ appendToDeps: clean
48
+ params:
49
+ root: ${PROJECTDIR}
50
+ to_build_first: ${workspaceSubProjectsToBuildFirst}
51
+ to_build: ${workspaceSubProjectsToBuild}
52
+ to_build_after: ${workspaceSubProjectsToBuildAfter}
53
+ excluded: ${workspaceSubProjectsToExclude}
54
+ args: clean ${workspaceBuildExtraArgs}
55
+ ignore_failures: ${workspaceBuildIgnoreFailures.clean}
56
+
57
+ # Workspace setup
58
+ workspace.setup:
59
+ description: Setup workspace projects
60
+ emoji: ":books:.:airplane_departure:"
61
+ builder: nmk_workspace.builders.SubProjectsBuilder
62
+ if: ${workspaceBuildEnabled.setup}
63
+ appendToDeps: setup
64
+ params:
65
+ root: ${PROJECTDIR}
66
+ to_build_first: ${workspaceSubProjectsToBuildFirst}
67
+ to_build: ${workspaceSubProjectsToBuild}
68
+ to_build_after: ${workspaceSubProjectsToBuildAfter}
69
+ excluded: ${workspaceSubProjectsToExclude}
70
+ args: setup ${workspaceBuildExtraArgs}
71
+ ignore_failures: ${workspaceBuildIgnoreFailures.setup}
72
+
73
+ # Workspace build
74
+ workspace.build:
75
+ description: Build workspace projects
76
+ emoji: ":books:.:hammer_and_wrench: "
77
+ builder: nmk_workspace.builders.SubProjectsBuilder
78
+ if: ${workspaceBuildEnabled.build}
79
+ appendToDeps: build
80
+ params:
81
+ root: ${PROJECTDIR}
82
+ to_build_first: ${workspaceSubProjectsToBuildFirst}
83
+ to_build: ${workspaceSubProjectsToBuild}
84
+ to_build_after: ${workspaceSubProjectsToBuildAfter}
85
+ excluded: ${workspaceSubProjectsToExclude}
86
+ args: build ${workspaceBuildExtraArgs}
87
+ ignore_failures: ${workspaceBuildIgnoreFailures.build}
88
+
89
+ # Workspace tests
90
+ workspace.tests:
91
+ description: Test workspace projects
92
+ emoji: ":books:.:crossed_fingers:"
93
+ builder: nmk_workspace.builders.SubProjectsBuilder
94
+ if: ${workspaceBuildEnabled.tests}
95
+ appendToDeps: tests
96
+ params:
97
+ root: ${PROJECTDIR}
98
+ to_build_first: ${workspaceSubProjectsToBuildFirst}
99
+ to_build: ${workspaceSubProjectsToBuild}
100
+ to_build_after: ${workspaceSubProjectsToBuildAfter}
101
+ excluded: ${workspaceSubProjectsToExclude}
102
+ args: tests ${workspaceBuildExtraArgs}
103
+ ignore_failures: ${workspaceBuildIgnoreFailures.tests}
104
+
105
+ # Workspace package
106
+ workspace.package:
107
+ description: Package workspace projects
108
+ emoji: ":books:.:package:"
109
+ builder: nmk_workspace.builders.SubProjectsBuilder
110
+ if: ${workspaceBuildEnabled.package}
111
+ appendToDeps: package
112
+ params:
113
+ root: ${PROJECTDIR}
114
+ to_build_first: ${workspaceSubProjectsToBuildFirst}
115
+ to_build: ${workspaceSubProjectsToBuild}
116
+ to_build_after: ${workspaceSubProjectsToBuildAfter}
117
+ excluded: ${workspaceSubProjectsToExclude}
118
+ args: package ${workspaceBuildExtraArgs}
119
+ ignore_failures: ${workspaceBuildIgnoreFailures.package}
@@ -0,0 +1,52 @@
1
+ Metadata-Version: 2.4
2
+ Name: nmk-workspace
3
+ Version: 1.0.0
4
+ Summary: VWorkspace handling plugin for nmk build system
5
+ Author: The dynod project
6
+ Maintainer: The dynod project
7
+ License: MIT License
8
+ Project-URL: Homepage, https://github.com/dynod/nmk-workspace
9
+ Project-URL: Repository, https://github.com/dynod/nmk-workspace
10
+ Project-URL: Issues, https://github.com/dynod/nmk/issues?q=is%3Aopen+is%3Aissue+label%3Aplugin%3Aworkspace
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Requires-Python: >=3.9
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Requires-Dist: nmk-base
20
+ Dynamic: license-file
21
+
22
+ # nmk-workspace
23
+ Workspace handling plugin for nmk build system
24
+
25
+ <!-- NMK-BADGES-BEGIN -->
26
+ [![License: MIT License](https://img.shields.io/github/license/dynod/nmk-workspace)](https://github.com/dynod/nmk-workspace/blob/main/LICENSE)
27
+ [![Checks](https://img.shields.io/github/actions/workflow/status/dynod/nmk-workspace/build.yml?branch=main&label=build%20%26%20u.t.)](https://github.com/dynod/nmk-workspace/actions?query=branch%3Amain)
28
+ [![Issues](https://img.shields.io/github/issues-search/dynod/nmk?label=issues&query=is%3Aopen+is%3Aissue+label%3Aplugin%3Aworkspace)](https://github.com/dynod/nmk/issues?q=is%3Aopen+is%3Aissue+label%3Aplugin%3Aworkspace)
29
+ [![Supported python versions](https://img.shields.io/badge/python-3.9%20--%203.13-blue)](https://www.python.org/)
30
+ [![PyPI](https://img.shields.io/pypi/v/nmk-workspace)](https://pypi.org/project/nmk-workspace/)
31
+ [![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://astral.sh/ruff)
32
+ [![Code coverage](https://img.shields.io/codecov/c/github/dynod/nmk-workspace)](https://app.codecov.io/gh/dynod/nmk-workspace)
33
+ [![Documentation Status](https://readthedocs.org/projects/nmk-workspace/badge/?version=stable)](https://nmk-workspace.readthedocs.io/)
34
+ <!-- NMK-BADGES-END -->
35
+
36
+ This plugin helps to recursively trigger tasks in subprojects (i.e. usually projects located in git submodules), using a configurable build order.
37
+
38
+ ## Usage
39
+
40
+ To use this plugin in your **`nmk`** project, insert this reference:
41
+ ```yaml
42
+ refs:
43
+ - pip://nmk-workspace!plugin.yml
44
+ ```
45
+
46
+ ## Documentation
47
+
48
+ This plugin documentation is available [here](https://nmk-workspace.readthedocs.io/)
49
+
50
+ ## Issues
51
+
52
+ Issues for this plugin shall be reported on the [main **`nmk`** project](https://github.com/dynod/nmk/issues), using the **plugin:workspace** label.
@@ -0,0 +1,10 @@
1
+ nmk_workspace/__init__.py,sha256=kQlFMMHO0VocMp9NDSXFJ9c9Sv_5EjtqqbjVyJIN6Ho,567
2
+ nmk_workspace/builders.py,sha256=mZNsibKw33lMTZVDAWaAPZDp2NaJZl-AM-pNdr5Do3w,3062
3
+ nmk_workspace/plugin.yml,sha256=VE8tXDyqJB_B61rJJROV81tffNjXyPAIEdhgP1HoPlg,430
4
+ nmk_workspace/resolvers.py,sha256=POnneUHHVuEd76AP4pIRw5hTNoIXjt_pLFqbglKWTIA,1545
5
+ nmk_workspace/subprojects.yml,sha256=8ShBixowHpoAb2rJARocTEsCTd45hQOSGcpVMgMf9-o,3925
6
+ nmk_workspace-1.0.0.dist-info/licenses/LICENSE,sha256=9Vf93wlBb5DSHKsJffyMcdUJiIUiClsINS651UP81jA,1062
7
+ nmk_workspace-1.0.0.dist-info/METADATA,sha256=q8wV2UGYSeJAiIP5XrIoIXAZn90KCCEQS51zEjcQl7s,2616
8
+ nmk_workspace-1.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
9
+ nmk_workspace-1.0.0.dist-info/top_level.txt,sha256=Vdlnly8TiJTHyLhbU2cI0TiNNqX-hvDvP0_BMH751Zs,14
10
+ nmk_workspace-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 dynod
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ nmk_workspace