yanga 0.1.0__tar.gz

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.
yanga-0.1.0/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+
2
+ MIT License
3
+
4
+ Copyright (c) 2022 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.
yanga-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,125 @@
1
+ Metadata-Version: 2.1
2
+ Name: yanga
3
+ Version: 0.1.0
4
+ Summary: Yet another ninja generator to build C/CPP projects.
5
+ Home-page: https://github.com/cuinixam/yanga
6
+ License: MIT
7
+ Author: cuinixam
8
+ Author-email: me@cuinixam.com
9
+ Requires-Python: >=3.9,<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.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Topic :: Software Development :: Libraries
20
+ Requires-Dist: loguru (>=0.7.0,<0.8.0)
21
+ Requires-Dist: mashumaro (>=3.5,<4.0)
22
+ Project-URL: Bug Tracker, https://github.com/cuinixam/yanga/issues
23
+ Project-URL: Changelog, https://github.com/cuinixam/yanga/blob/main/CHANGELOG.md
24
+ Project-URL: Documentation, https://yanga.readthedocs.io
25
+ Project-URL: Repository, https://github.com/cuinixam/yanga
26
+ Description-Content-Type: text/markdown
27
+
28
+ # README
29
+
30
+ <p align="center">
31
+ <a href="https://github.com/cuinixam/yanga/actions/workflows/ci.yml?query=branch%3Amain">
32
+ <img src="https://img.shields.io/github/actions/workflow/status/cuinixam/yanga/ci.yml?branch=main&label=CI&logo=github&style=flat-square" alt="CI Status" >
33
+ </a>
34
+ <a href="https://yanga.readthedocs.io">
35
+ <img src="https://img.shields.io/readthedocs/yanga.svg?logo=read-the-docs&logoColor=fff&style=flat-square" alt="Documentation Status">
36
+ </a>
37
+ <a href="https://codecov.io/gh/cuinixam/yanga">
38
+ <img src="https://img.shields.io/codecov/c/github/cuinixam/yanga.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/ambv/black">
46
+ <img src="https://img.shields.io/badge/code%20style-black-000000.svg?style=flat-square" alt="black">
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/yanga/">
54
+ <img src="https://img.shields.io/pypi/v/yanga.svg?logo=python&logoColor=fff&style=flat-square" alt="PyPI Version">
55
+ </a>
56
+ <img src="https://img.shields.io/pypi/pyversions/yanga.svg?style=flat-square&logo=python&amp;logoColor=fff" alt="Supported Python versions">
57
+ <img src="https://img.shields.io/pypi/l/yanga.svg?style=flat-square" alt="License">
58
+ </p>
59
+
60
+ Yet another ninja generator to build C/CPP projects.
61
+
62
+ ## Installation
63
+
64
+ Install this via pip (or your favourite package manager):
65
+
66
+ `pip install yanga`
67
+
68
+ ## Start developing
69
+
70
+ The project uses Poetry for dependencies management and packaging.
71
+ If you do not have Poetry installed, you can run the `boostrap.ps1` script.
72
+ This will install Python and Poetry as configured in `scoopfile.json`.
73
+
74
+ ```powershell
75
+ Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope CurrentUser -Force
76
+ .\bootstrap.ps1
77
+ ```
78
+
79
+ To install the development dependencies in a virtual environment, type:
80
+
81
+ ```shell
82
+ poetry install
83
+ ```
84
+
85
+ This will also generate a `poetry.lock` file, you should track this file in version control. To execute the test suite, call pytest inside Poetry's virtual environment via `poetry run`:
86
+
87
+ ```shell
88
+ poetry run pytest
89
+ ```
90
+
91
+ Check out the Poetry documentation for more information on the available commands.
92
+
93
+ For those using [VS Code](https://code.visualstudio.com/) there are tasks defined for the most common commands:
94
+
95
+ - install development dependencies
96
+ - run tests
97
+ - run all checks configured for pre-commit
98
+ - generate documentation
99
+
100
+ See the `.vscode/tasks.json` for more details.
101
+
102
+ ## Committing changes
103
+
104
+ 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).
105
+
106
+ ## Contributors ✨
107
+
108
+ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
109
+
110
+ <!-- prettier-ignore-start -->
111
+ <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
112
+ <!-- markdownlint-disable -->
113
+ <!-- markdownlint-enable -->
114
+ <!-- ALL-CONTRIBUTORS-LIST:END -->
115
+ <!-- prettier-ignore-end -->
116
+
117
+ This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
118
+
119
+ ## Credits
120
+
121
+ This package was created with
122
+ [Copier](https://copier.readthedocs.io/) and the
123
+ [browniebroke/pypackage-template](https://github.com/browniebroke/pypackage-template)
124
+ project template.
125
+
yanga-0.1.0/README.md ADDED
@@ -0,0 +1,97 @@
1
+ # README
2
+
3
+ <p align="center">
4
+ <a href="https://github.com/cuinixam/yanga/actions/workflows/ci.yml?query=branch%3Amain">
5
+ <img src="https://img.shields.io/github/actions/workflow/status/cuinixam/yanga/ci.yml?branch=main&label=CI&logo=github&style=flat-square" alt="CI Status" >
6
+ </a>
7
+ <a href="https://yanga.readthedocs.io">
8
+ <img src="https://img.shields.io/readthedocs/yanga.svg?logo=read-the-docs&logoColor=fff&style=flat-square" alt="Documentation Status">
9
+ </a>
10
+ <a href="https://codecov.io/gh/cuinixam/yanga">
11
+ <img src="https://img.shields.io/codecov/c/github/cuinixam/yanga.svg?logo=codecov&logoColor=fff&style=flat-square" alt="Test coverage percentage">
12
+ </a>
13
+ </p>
14
+ <p align="center">
15
+ <a href="https://python-poetry.org/">
16
+ <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">
17
+ </a>
18
+ <a href="https://github.com/ambv/black">
19
+ <img src="https://img.shields.io/badge/code%20style-black-000000.svg?style=flat-square" alt="black">
20
+ </a>
21
+ <a href="https://github.com/pre-commit/pre-commit">
22
+ <img src="https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=flat-square" alt="pre-commit">
23
+ </a>
24
+ </p>
25
+ <p align="center">
26
+ <a href="https://pypi.org/project/yanga/">
27
+ <img src="https://img.shields.io/pypi/v/yanga.svg?logo=python&logoColor=fff&style=flat-square" alt="PyPI Version">
28
+ </a>
29
+ <img src="https://img.shields.io/pypi/pyversions/yanga.svg?style=flat-square&logo=python&amp;logoColor=fff" alt="Supported Python versions">
30
+ <img src="https://img.shields.io/pypi/l/yanga.svg?style=flat-square" alt="License">
31
+ </p>
32
+
33
+ Yet another ninja generator to build C/CPP projects.
34
+
35
+ ## Installation
36
+
37
+ Install this via pip (or your favourite package manager):
38
+
39
+ `pip install yanga`
40
+
41
+ ## Start developing
42
+
43
+ The project uses Poetry for dependencies management and packaging.
44
+ If you do not have Poetry installed, you can run the `boostrap.ps1` script.
45
+ This will install Python and Poetry as configured in `scoopfile.json`.
46
+
47
+ ```powershell
48
+ Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope CurrentUser -Force
49
+ .\bootstrap.ps1
50
+ ```
51
+
52
+ To install the development dependencies in a virtual environment, type:
53
+
54
+ ```shell
55
+ poetry install
56
+ ```
57
+
58
+ This will also generate a `poetry.lock` file, you should track this file in version control. To execute the test suite, call pytest inside Poetry's virtual environment via `poetry run`:
59
+
60
+ ```shell
61
+ poetry run pytest
62
+ ```
63
+
64
+ Check out the Poetry documentation for more information on the available commands.
65
+
66
+ For those using [VS Code](https://code.visualstudio.com/) there are tasks defined for the most common commands:
67
+
68
+ - install development dependencies
69
+ - run tests
70
+ - run all checks configured for pre-commit
71
+ - generate documentation
72
+
73
+ See the `.vscode/tasks.json` for more details.
74
+
75
+ ## Committing changes
76
+
77
+ 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).
78
+
79
+ ## Contributors ✨
80
+
81
+ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
82
+
83
+ <!-- prettier-ignore-start -->
84
+ <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
85
+ <!-- markdownlint-disable -->
86
+ <!-- markdownlint-enable -->
87
+ <!-- ALL-CONTRIBUTORS-LIST:END -->
88
+ <!-- prettier-ignore-end -->
89
+
90
+ This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
91
+
92
+ ## Credits
93
+
94
+ This package was created with
95
+ [Copier](https://copier.readthedocs.io/) and the
96
+ [browniebroke/pypackage-template](https://github.com/browniebroke/pypackage-template)
97
+ project template.
@@ -0,0 +1,99 @@
1
+ [tool.poetry]
2
+ name = "yanga"
3
+ version = "0.1.0"
4
+ description = "Yet another ninja generator to build C/CPP projects."
5
+ authors = ["cuinixam <me@cuinixam.com>"]
6
+ license = "MIT"
7
+ readme = "README.md"
8
+ repository = "https://github.com/cuinixam/yanga"
9
+ documentation = "https://yanga.readthedocs.io"
10
+ classifiers = [
11
+ "Development Status :: 2 - Pre-Alpha",
12
+ "Intended Audience :: Developers",
13
+ "Natural Language :: English",
14
+ "Operating System :: OS Independent",
15
+ "Topic :: Software Development :: Libraries",
16
+ ]
17
+ packages = [
18
+ { include = "yanga", from = "src" },
19
+ ]
20
+
21
+ [tool.poetry.urls]
22
+ "Bug Tracker" = "https://github.com/cuinixam/yanga/issues"
23
+ "Changelog" = "https://github.com/cuinixam/yanga/blob/main/CHANGELOG.md"
24
+
25
+ [tool.poetry.dependencies]
26
+ python = "^3.9"
27
+ mashumaro = "^3.5"
28
+ loguru = "^0.7.0"
29
+
30
+ [tool.poetry.group.dev.dependencies]
31
+ pytest = "^7.0"
32
+ pytest-cov = "^4.0"
33
+ black = "^23.1.0"
34
+ pre-commit = "^3.1.1"
35
+
36
+ [tool.poetry.group.docs]
37
+ optional = true
38
+
39
+ [tool.poetry.group.docs.dependencies]
40
+ myst-parser = ">=0.16"
41
+ sphinx = ">=4.0"
42
+ sphinx-rtd-theme = ">=1.0"
43
+ m2r = "^0.3.1"
44
+ sphinxcontrib-mermaid = "^0.8.1"
45
+ sphinxcontrib-bibtex = "^2.5.0"
46
+ mlx-traceability = "^10.0.0"
47
+
48
+ [tool.semantic_release]
49
+ branch = "main"
50
+ version_toml = "pyproject.toml:tool.poetry.version"
51
+ version_variable = "src/yanga/__init__.py:__version__"
52
+ build_command = "pip install poetry && poetry build"
53
+
54
+ [tool.pytest.ini_options]
55
+ addopts = "-v -Wdefault --cov=yanga --cov-report=term-missing:skip-covered -s"
56
+ pythonpath = ["src"]
57
+
58
+ [tool.coverage.run]
59
+ branch = true
60
+
61
+ [tool.coverage.report]
62
+ exclude_lines = [
63
+ "pragma: no cover",
64
+ "@overload",
65
+ "if TYPE_CHECKING",
66
+ "raise NotImplementedError",
67
+ 'if __name__ == "__main__":',
68
+ ]
69
+
70
+ [tool.isort]
71
+ profile = "black"
72
+ known_first_party = ["yanga", "tests"]
73
+
74
+ [tool.mypy]
75
+ check_untyped_defs = true
76
+ disallow_any_generics = true
77
+ disallow_incomplete_defs = true
78
+ disallow_untyped_defs = true
79
+ mypy_path = "src/"
80
+ no_implicit_optional = true
81
+ show_error_codes = true
82
+ warn_unreachable = true
83
+ warn_unused_ignores = true
84
+ exclude = [
85
+ 'docs/.*',
86
+ 'setup.py',
87
+ ]
88
+
89
+ [[tool.mypy.overrides]]
90
+ module = "tests.*"
91
+ allow_untyped_defs = true
92
+
93
+ [[tool.mypy.overrides]]
94
+ module = "docs.*"
95
+ ignore_errors = true
96
+
97
+ [build-system]
98
+ requires = ["poetry-core>=1.0.0"]
99
+ build-backend = "poetry.core.masonry.api"
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"
File without changes
@@ -0,0 +1,83 @@
1
+ from abc import ABC, abstractmethod
2
+ from argparse import ArgumentError, ArgumentParser, Namespace
3
+ from typing import Dict, List
4
+
5
+ from yanga.core.docs_utils import fulfills
6
+ from yanga.core.logger import logger
7
+
8
+
9
+ class Command(ABC):
10
+ def __init__(self, name: str, description: str) -> None:
11
+ self.name = name
12
+ self.description = description
13
+ self.parser: ArgumentParser
14
+
15
+ @abstractmethod
16
+ def run(self, args: Namespace) -> int:
17
+ """Run the command with the provided arguments."""
18
+
19
+ def register_parser(self, parser_adder) -> None: # type: ignore
20
+ """Register the command parser.
21
+
22
+ :param parser_adder: The return value of ``ArgumentParser.add_subparsers()``
23
+ """
24
+ self.parser = parser_adder.add_parser(
25
+ self.name, help=self.description, exit_on_error=False
26
+ )
27
+ self._register_arguments(self.parser)
28
+
29
+ @abstractmethod
30
+ def _register_arguments(self, parser: ArgumentParser) -> None:
31
+ """Register arguments for the command."""
32
+
33
+
34
+ class CommandLineHandler:
35
+ """Handles the command line interface."""
36
+
37
+ def __init__(self, commands: Dict[str, Command], parser: ArgumentParser) -> None:
38
+ super().__init__()
39
+ self.commands = commands
40
+ self.parser = parser
41
+ self.logger = logger.bind()
42
+
43
+ @fulfills("REQ-CMDLINE_COMMAND_ARGS-0.0.1", "REQ-CMDLINE_COMMAND_EXEC-0.0.1")
44
+ def run(self, args: List[str]) -> int:
45
+ try:
46
+ parsed_args = self.parser.parse_args(args)
47
+ except ArgumentError as e:
48
+ self.logger.error(f"Argument error: {e}")
49
+ self.parser.print_help()
50
+ return 1
51
+ if (args is None) or (len(args) == 0):
52
+ self.logger.debug("No command provided")
53
+ self.parser.print_help()
54
+ return 1
55
+ command = self.commands.get(args[0], None)
56
+ if command:
57
+ return command.run(parsed_args)
58
+ else:
59
+ self.logger.error(f"Command {args[0]} not registered")
60
+ return 1
61
+
62
+
63
+ class CommandLineHandlerBuilder:
64
+ """Builds a command line handler."""
65
+
66
+ def __init__(self) -> None:
67
+ self.commands: Dict[str, Command] = {}
68
+ self.parser = ArgumentParser(
69
+ prog="yanga", description="Yanga CLI", exit_on_error=False
70
+ )
71
+ self.subparsers = self.parser.add_subparsers(title="Commands", dest="command")
72
+
73
+ def create(self) -> CommandLineHandler:
74
+ return CommandLineHandler(self.commands, self.parser)
75
+
76
+ @fulfills("REQ-CMDLINE_REGISTER_COMMANDS-0.0.1", "REQ-CMDLINE_DUPLICATION-0.0.1")
77
+ def add_command(self, command: Command) -> "CommandLineHandlerBuilder":
78
+ """Add a command to the command line handler."""
79
+ if self.commands.get(command.name, None) is not None:
80
+ raise ValueError(f"Command {command.name} already exists")
81
+ self.commands[command.name] = command
82
+ command.register_parser(self.subparsers)
83
+ return self
@@ -0,0 +1,35 @@
1
+ from typing import Any, Callable
2
+
3
+
4
+ def validates(*req_ids: str) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
5
+ def _doc(func: Callable[..., Any]) -> Callable[..., Any]:
6
+ user_doc = func.__doc__ or ""
7
+ req_ids_str = " ".join(req_ids)
8
+ func.__doc__ = (
9
+ user_doc
10
+ + "\n"
11
+ + f"""
12
+ .. item:: UTEST-{func.__module__}.{func.__qualname__}
13
+ :validates: {req_ids_str}
14
+ """
15
+ )
16
+ return func
17
+
18
+ return _doc
19
+
20
+
21
+ def fulfills(*req_ids: str) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
22
+ def _doc(func: Callable[..., Any]) -> Callable[..., Any]:
23
+ user_doc = func.__doc__ or ""
24
+ req_ids_str = " ".join(req_ids)
25
+ func.__doc__ = (
26
+ user_doc
27
+ + "\n"
28
+ + f"""
29
+ .. item:: IMPL-{func.__module__}.{func.__qualname__}
30
+ :fulfills: {req_ids_str}
31
+ """
32
+ )
33
+ return func
34
+
35
+ return _doc
@@ -0,0 +1,52 @@
1
+ """ Logging utilities. """
2
+
3
+ import sys
4
+ import time
5
+ from pathlib import Path
6
+ from typing import Any, Callable, Optional
7
+
8
+ from loguru import logger as _logger
9
+
10
+ from .docs_utils import fulfills
11
+
12
+ logger = _logger
13
+
14
+ # Adding custom logging levels
15
+ logger.level("START", no=38, color="<yellow>")
16
+ logger.level("STOP", no=39, color="<yellow>")
17
+
18
+
19
+ @fulfills("REQ-LOGGING_TIME_IT-0.0.1")
20
+ def time_it(message: Optional[str] = None) -> Callable[..., Any]:
21
+ """Decorator to time a function."""
22
+
23
+ def _time_it(func: Callable[..., Any]) -> Callable[..., Any]:
24
+ text = message or f"{func.__module__}.{func.__qualname__}"
25
+
26
+ def time_it(*args: Any, **kwargs: Any) -> Any:
27
+ start_time = time.time()
28
+ logger.log("START", f"Starting {text}")
29
+ result = func(*args, **kwargs)
30
+ end_time = time.time()
31
+ logger.log("STOP", f"Finished {text} in {end_time-start_time:.2f}s")
32
+ return result
33
+
34
+ return time_it
35
+
36
+ return _time_it
37
+
38
+
39
+ @fulfills("REQ-LOGGING_FILE-0.0.1")
40
+ def setup_logger(log_file: Optional[Path] = None, clear: bool = True) -> None:
41
+ """Setup logger to stdout and optionally to file."""
42
+ logger.remove()
43
+ logger.add(
44
+ sys.stdout,
45
+ format="<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | "
46
+ "<level>{level: <8}</level> | <level>{message}</level>",
47
+ )
48
+ if log_file is not None:
49
+ logger.add(log_file, level="DEBUG")
50
+ # Clear log file
51
+ if log_file.exists() and clear:
52
+ log_file.write_text("")
File without changes
File without changes
@@ -0,0 +1,32 @@
1
+ from dataclasses import dataclass, field
2
+ from typing import List, Optional
3
+
4
+ from mashumaro.mixins.yaml import DataClassYAMLMixin
5
+
6
+
7
+ @dataclass
8
+ class VariantConfig(DataClassYAMLMixin):
9
+ """
10
+ .. item:: IMPL-VariantConfig
11
+ :fulfills:
12
+ REQ-VARIANT_NAME-0.0.1
13
+ REQ-VARIANT_SLUG-0.0.1
14
+ REQ-VARIANT_DESCRIPTION-0.0.1
15
+ REQ-VARIANT_TAGS-0.0.1
16
+ """
17
+
18
+ name: str
19
+ description: Optional[str] = None
20
+ tags: List[str] = field(default_factory=list)
21
+ _slug: Optional[str] = None
22
+
23
+ def generate_slug(self, slug: Optional[str] = None) -> str:
24
+ return (slug or self.name).lower().replace(" ", "-")
25
+
26
+ @property
27
+ def slug(self) -> str:
28
+ return self._slug or self.generate_slug()
29
+
30
+ @slug.setter
31
+ def slug(self, slug: str) -> None:
32
+ self._slug = self.generate_slug(slug)
@@ -0,0 +1,23 @@
1
+ import time
2
+ from argparse import ArgumentParser, Namespace
3
+ from pathlib import Path
4
+
5
+ from yanga.core.cmd_line import Command
6
+ from yanga.core.logger import logger, time_it
7
+
8
+
9
+ class BuildCommand(Command):
10
+ def __init__(self) -> None:
11
+ super().__init__("build", "Build a yanga project")
12
+ self.logger = logger.bind()
13
+
14
+ @time_it()
15
+ def run(self, args: Namespace) -> int:
16
+ self.logger.info(f"Running {self.name} with args {args}")
17
+ time.sleep(0.3)
18
+ return 0
19
+
20
+ def _register_arguments(self, parser: ArgumentParser) -> None:
21
+ parser.add_argument(
22
+ "--project-dir", help="Project directory", default=Path("."), type=Path
23
+ )
@@ -0,0 +1,23 @@
1
+ import time
2
+ from argparse import ArgumentParser, Namespace
3
+ from pathlib import Path
4
+
5
+ from yanga.core.cmd_line import Command
6
+ from yanga.core.logger import logger, time_it
7
+
8
+
9
+ class InitCommand(Command):
10
+ def __init__(self) -> None:
11
+ super().__init__("init", "Init a yanga project")
12
+ self.logger = logger.bind()
13
+
14
+ @time_it()
15
+ def run(self, args: Namespace) -> int:
16
+ self.logger.info(f"Running {self.name} with args {args}")
17
+ time.sleep(0.3)
18
+ return 0
19
+
20
+ def _register_arguments(self, parser: ArgumentParser) -> None:
21
+ parser.add_argument(
22
+ "--project-dir", help="Project directory", default=Path("."), type=Path
23
+ )
@@ -0,0 +1,25 @@
1
+ from pathlib import Path
2
+ from sys import argv
3
+
4
+ from yanga.core.cmd_line import CommandLineHandlerBuilder
5
+ from yanga.core.logger import logger, setup_logger, time_it
6
+ from yanga.ybuild import BuildCommand
7
+ from yanga.yinit import InitCommand
8
+
9
+
10
+ @time_it()
11
+ def do_run() -> None:
12
+ logger.debug("Starting yanga")
13
+ builder = CommandLineHandlerBuilder()
14
+ builder.add_command(BuildCommand()).add_command(InitCommand())
15
+ handler = builder.create()
16
+ handler.run(argv[1:])
17
+
18
+
19
+ def main() -> None:
20
+ setup_logger(Path(".yanga/logs/yanga.log"), clear=True)
21
+ do_run()
22
+
23
+
24
+ if __name__ == "__main__":
25
+ main()