poks 0.0.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.
poks-0.0.0/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+
2
+ MIT License
3
+
4
+ Copyright (c) 2026 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.
poks-0.0.0/PKG-INFO ADDED
@@ -0,0 +1,159 @@
1
+ Metadata-Version: 2.4
2
+ Name: poks
3
+ Version: 0.0.0
4
+ Summary: A lightweight archive downloader for pre-build binary dependencies.
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Author: cuinixam
8
+ Author-email: me@cuinixam.com
9
+ Requires-Python: >=3.10
10
+ Classifier: Development Status :: 2 - Pre-Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Natural Language :: English
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Topic :: Software Development :: Libraries
20
+ Requires-Dist: mashumaro (>=3.13,<4)
21
+ Requires-Dist: py-app-dev (>=2.1,<3)
22
+ Requires-Dist: typer (>=0,<1)
23
+ Project-URL: Bug Tracker, https://github.com/cuinixam/poks/issues
24
+ Project-URL: Changelog, https://github.com/cuinixam/poks/blob/main/CHANGELOG.md
25
+ Project-URL: Repository, https://github.com/cuinixam/poks
26
+ Description-Content-Type: text/markdown
27
+
28
+ # Poks
29
+
30
+ <p align="center">
31
+ <a href="https://github.com/cuinixam/poks/actions/workflows/ci.yml?query=branch%3Amain">
32
+ <img src="https://img.shields.io/github/actions/workflow/status/cuinixam/poks/ci.yml?branch=main&label=CI&logo=github&style=flat-square" alt="CI Status" >
33
+ </a>
34
+ <a href="https://codecov.io/gh/cuinixam/poks">
35
+ <img src="https://img.shields.io/codecov/c/github/cuinixam/poks.svg?logo=codecov&logoColor=fff&style=flat-square" alt="Test coverage percentage">
36
+ </a>
37
+ </p>
38
+ <p align="center">
39
+ <a href="https://github.com/astral-sh/uv">
40
+ <img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json" alt="uv">
41
+ </a>
42
+ <a href="https://github.com/astral-sh/ruff">
43
+ <img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff">
44
+ </a>
45
+ <a href="https://github.com/cuinixam/pypeline">
46
+ <img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/cuinixam/pypeline/refs/heads/main/assets/badge/v0.json" alt="pypeline">
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/poks/">
54
+ <img src="https://img.shields.io/pypi/v/poks.svg?logo=python&logoColor=fff&style=flat-square" alt="PyPI Version">
55
+ </a>
56
+ <img src="https://img.shields.io/pypi/pyversions/poks.svg?style=flat-square&logo=python&amp;logoColor=fff" alt="Supported Python versions">
57
+ <img src="https://img.shields.io/pypi/l/poks.svg?style=flat-square" alt="License">
58
+ </p>
59
+
60
+ ---
61
+
62
+ **Source Code**: <a href="https://github.com/cuinixam/poks" target="_blank">https://github.com/cuinixam/poks</a>
63
+
64
+ ---
65
+
66
+ A lightweight, cross-platform archive downloader for pre-built binary dependencies. Inspired by [Scoop](https://scoop.sh/), Poks provides a uniform way to install and manage developer tools using simple JSON manifests.
67
+
68
+ ## Features
69
+
70
+ - **Cross-Platform**: Works on Windows, Linux, and macOS
71
+ - **No Admin Rights**: Installs tools in user space
72
+ - **Deterministic**: Pin exact versions in manifests for reproducible builds
73
+ - **Relocatable**: The apps directory is self-contained and portable
74
+
75
+ ## Installation
76
+
77
+ Install via pipx(or your favorite package manager):
78
+
79
+ ```bash
80
+ pipx install poks
81
+ ```
82
+
83
+ ## Quick Start
84
+
85
+ Create a `poks.json` configuration file:
86
+
87
+ ```json
88
+ {
89
+ "buckets": [
90
+ {
91
+ "name": "main",
92
+ "url": "https://github.com/poks/main-bucket.git"
93
+ }
94
+ ],
95
+ "apps": [
96
+ {
97
+ "name": "cmake",
98
+ "version": "3.28.1",
99
+ "bucket": "main"
100
+ }
101
+ ]
102
+ }
103
+ ```
104
+
105
+ Install the defined tools:
106
+
107
+ ```bash
108
+ poks install -c poks.json
109
+ ```
110
+
111
+ ## CLI Commands
112
+
113
+ ```bash
114
+ # Install tools from config file
115
+ poks install -c poks.json
116
+
117
+ # Install a specific tool
118
+ poks install zephyr-sdk@0.16.5-1 --bucket main
119
+
120
+ # Uninstall a specific version
121
+ poks uninstall zephyr-sdk@0.16.5-1
122
+
123
+ # Uninstall all versions of an app
124
+ poks uninstall zephyr-sdk
125
+
126
+ # Uninstall everything
127
+ poks uninstall --all
128
+ ```
129
+
130
+ ## Documentation
131
+
132
+ For detailed specifications and manifest format, see [docs/specs.md](docs/specs.md).
133
+
134
+ ## Development
135
+
136
+ This project uses [pypeline](https://github.com/cuinixam/pypeline) for build automation.
137
+
138
+ ```bash
139
+ # Run full pipeline (lint + tests)
140
+ pypeline run
141
+
142
+ # Run only linting
143
+ pypeline run --step PreCommit
144
+
145
+ # Run tests with specific Python version
146
+ pypeline run --step CreateVEnv --step PyTest --single --input python_version=3.13
147
+ ```
148
+
149
+ For AI agents and contributors, see [AGENTS.md](AGENTS.md) for development guidelines.
150
+
151
+ ## Credits
152
+
153
+ [![Copier](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/copier-org/copier/master/img/badge/badge-grayscale-inverted-border-orange.json)](https://github.com/copier-org/copier)
154
+
155
+ This package was created with
156
+ [Copier](https://copier.readthedocs.io/) and the
157
+ [browniebroke/pypackage-template](https://github.com/browniebroke/pypackage-template)
158
+ project template.
159
+
poks-0.0.0/README.md ADDED
@@ -0,0 +1,131 @@
1
+ # Poks
2
+
3
+ <p align="center">
4
+ <a href="https://github.com/cuinixam/poks/actions/workflows/ci.yml?query=branch%3Amain">
5
+ <img src="https://img.shields.io/github/actions/workflow/status/cuinixam/poks/ci.yml?branch=main&label=CI&logo=github&style=flat-square" alt="CI Status" >
6
+ </a>
7
+ <a href="https://codecov.io/gh/cuinixam/poks">
8
+ <img src="https://img.shields.io/codecov/c/github/cuinixam/poks.svg?logo=codecov&logoColor=fff&style=flat-square" alt="Test coverage percentage">
9
+ </a>
10
+ </p>
11
+ <p align="center">
12
+ <a href="https://github.com/astral-sh/uv">
13
+ <img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json" alt="uv">
14
+ </a>
15
+ <a href="https://github.com/astral-sh/ruff">
16
+ <img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff">
17
+ </a>
18
+ <a href="https://github.com/cuinixam/pypeline">
19
+ <img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/cuinixam/pypeline/refs/heads/main/assets/badge/v0.json" alt="pypeline">
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/poks/">
27
+ <img src="https://img.shields.io/pypi/v/poks.svg?logo=python&logoColor=fff&style=flat-square" alt="PyPI Version">
28
+ </a>
29
+ <img src="https://img.shields.io/pypi/pyversions/poks.svg?style=flat-square&logo=python&amp;logoColor=fff" alt="Supported Python versions">
30
+ <img src="https://img.shields.io/pypi/l/poks.svg?style=flat-square" alt="License">
31
+ </p>
32
+
33
+ ---
34
+
35
+ **Source Code**: <a href="https://github.com/cuinixam/poks" target="_blank">https://github.com/cuinixam/poks</a>
36
+
37
+ ---
38
+
39
+ A lightweight, cross-platform archive downloader for pre-built binary dependencies. Inspired by [Scoop](https://scoop.sh/), Poks provides a uniform way to install and manage developer tools using simple JSON manifests.
40
+
41
+ ## Features
42
+
43
+ - **Cross-Platform**: Works on Windows, Linux, and macOS
44
+ - **No Admin Rights**: Installs tools in user space
45
+ - **Deterministic**: Pin exact versions in manifests for reproducible builds
46
+ - **Relocatable**: The apps directory is self-contained and portable
47
+
48
+ ## Installation
49
+
50
+ Install via pipx(or your favorite package manager):
51
+
52
+ ```bash
53
+ pipx install poks
54
+ ```
55
+
56
+ ## Quick Start
57
+
58
+ Create a `poks.json` configuration file:
59
+
60
+ ```json
61
+ {
62
+ "buckets": [
63
+ {
64
+ "name": "main",
65
+ "url": "https://github.com/poks/main-bucket.git"
66
+ }
67
+ ],
68
+ "apps": [
69
+ {
70
+ "name": "cmake",
71
+ "version": "3.28.1",
72
+ "bucket": "main"
73
+ }
74
+ ]
75
+ }
76
+ ```
77
+
78
+ Install the defined tools:
79
+
80
+ ```bash
81
+ poks install -c poks.json
82
+ ```
83
+
84
+ ## CLI Commands
85
+
86
+ ```bash
87
+ # Install tools from config file
88
+ poks install -c poks.json
89
+
90
+ # Install a specific tool
91
+ poks install zephyr-sdk@0.16.5-1 --bucket main
92
+
93
+ # Uninstall a specific version
94
+ poks uninstall zephyr-sdk@0.16.5-1
95
+
96
+ # Uninstall all versions of an app
97
+ poks uninstall zephyr-sdk
98
+
99
+ # Uninstall everything
100
+ poks uninstall --all
101
+ ```
102
+
103
+ ## Documentation
104
+
105
+ For detailed specifications and manifest format, see [docs/specs.md](docs/specs.md).
106
+
107
+ ## Development
108
+
109
+ This project uses [pypeline](https://github.com/cuinixam/pypeline) for build automation.
110
+
111
+ ```bash
112
+ # Run full pipeline (lint + tests)
113
+ pypeline run
114
+
115
+ # Run only linting
116
+ pypeline run --step PreCommit
117
+
118
+ # Run tests with specific Python version
119
+ pypeline run --step CreateVEnv --step PyTest --single --input python_version=3.13
120
+ ```
121
+
122
+ For AI agents and contributors, see [AGENTS.md](AGENTS.md) for development guidelines.
123
+
124
+ ## Credits
125
+
126
+ [![Copier](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/copier-org/copier/master/img/badge/badge-grayscale-inverted-border-orange.json)](https://github.com/copier-org/copier)
127
+
128
+ This package was created with
129
+ [Copier](https://copier.readthedocs.io/) and the
130
+ [browniebroke/pypackage-template](https://github.com/browniebroke/pypackage-template)
131
+ project template.
@@ -0,0 +1,169 @@
1
+ [project]
2
+ name = "poks"
3
+ version = "0.0.0"
4
+ description = "A lightweight archive downloader for pre-build binary dependencies."
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ authors = [
8
+ { name = "cuinixam", email = "me@cuinixam.com" },
9
+ ]
10
+ requires-python = ">=3.10"
11
+ classifiers = [
12
+ "Development Status :: 2 - Pre-Alpha",
13
+ "Intended Audience :: Developers",
14
+ "Natural Language :: English",
15
+ "Operating System :: OS Independent",
16
+ "Programming Language :: Python :: 3.10",
17
+ "Programming Language :: Python :: 3.11",
18
+ "Programming Language :: Python :: 3.12",
19
+ "Programming Language :: Python :: 3.13",
20
+ "Programming Language :: Python :: 3.14",
21
+ "Topic :: Software Development :: Libraries",
22
+ ]
23
+
24
+ dependencies = [
25
+ "py-app-dev>=2.1,<3",
26
+ "typer>=0,<1",
27
+ "mashumaro>=3.13,<4",
28
+ ]
29
+ urls."Bug Tracker" = "https://github.com/cuinixam/poks/issues"
30
+ urls.Changelog = "https://github.com/cuinixam/poks/blob/main/CHANGELOG.md"
31
+ urls.repository = "https://github.com/cuinixam/poks"
32
+
33
+ [project.scripts]
34
+ poks = "poks.main:main"
35
+
36
+ [build-system]
37
+ requires = ["poetry-core>=2,<3"]
38
+ build-backend = "poetry.core.masonry.api"
39
+
40
+ [dependency-groups]
41
+ dev = [
42
+ "pytest==9.*",
43
+ "sybil[pytest]",
44
+ "coverage",
45
+ "pytest-cov==7.*",
46
+ "pypeline-runner>=1,<2",
47
+ "pre-commit>=4,<5",
48
+ "ruff>=0,<1",
49
+ ]
50
+
51
+ [tool.ruff]
52
+ line-length = 180
53
+ lint.select = [
54
+ "B", # flake8-bugbear
55
+ "D", # flake8-docstrings
56
+ "C4", # flake8-comprehensions
57
+ "S", # flake8-bandit
58
+ "F", # pyflake
59
+ "E", # pycodestyle
60
+ "W", # pycodestyle
61
+ "UP", # pyupgrade
62
+ "I", # isort
63
+ "RUF", # ruff specific
64
+ ]
65
+ lint.ignore = [
66
+ "D103",
67
+ "D203", # 1 blank line required before class docstring
68
+ "D212", # Multi-line docstring summary should start at the first line
69
+ "D100", # Missing docstring in public module
70
+ "D104", # Missing docstring in public package
71
+ "D107", # Missing docstring in `__init__`
72
+ "D401", # First line of docstring should be in imperative mood
73
+ ]
74
+ lint.per-file-ignores."conftest.py" = [ "D100" ]
75
+ lint.per-file-ignores."setup.py" = [ "D100" ]
76
+ lint.per-file-ignores."tests/**/*" = [
77
+ "D100",
78
+ "D101",
79
+ "D102",
80
+ "D103",
81
+ "D104",
82
+ "S101",
83
+ ]
84
+ lint.isort.known-first-party = [ "poks", "tests" ]
85
+
86
+ [tool.pyproject-fmt]
87
+ max_supported_python = "3.14"
88
+
89
+ [tool.pytest.ini_options]
90
+ addopts = """\
91
+ -v
92
+ -Wdefault
93
+ -p no:doctest
94
+ --cov=poks
95
+ --cov-report=term
96
+ --cov-report=xml
97
+ """
98
+ pythonpath = [ "src" ]
99
+
100
+ [tool.coverage.run]
101
+ branch = true
102
+
103
+ [tool.coverage.paths]
104
+ source = [
105
+ "src",
106
+ ".tox/**/site-packages",
107
+ ]
108
+
109
+ [tool.coverage.report]
110
+ exclude_lines = [
111
+ "pragma: no cover",
112
+ "@overload",
113
+ "if TYPE_CHECKING",
114
+ "raise NotImplementedError",
115
+ 'if __name__ == "__main__":',
116
+ ]
117
+
118
+ [tool.mypy]
119
+ check_untyped_defs = true
120
+ disallow_any_generics = true
121
+ disallow_incomplete_defs = true
122
+ disallow_untyped_defs = true
123
+ mypy_path = "src/"
124
+ no_implicit_optional = true
125
+ show_error_codes = true
126
+ warn_unreachable = true
127
+ warn_unused_ignores = true
128
+ exclude = [
129
+ 'setup.py',
130
+ ]
131
+
132
+ [[tool.mypy.overrides]]
133
+ module = "tests.*"
134
+ allow_untyped_defs = true
135
+
136
+ [tool.semantic_release]
137
+ allow_zero_version = true
138
+ version_toml = [ "pyproject.toml:project.version" ]
139
+ version_variables = [
140
+ "src/poks/__init__.py:__version__",
141
+ ]
142
+ build_command = """
143
+ pip install uv
144
+ uv lock
145
+ git add uv.lock
146
+ uv build
147
+ """
148
+
149
+ [tool.semantic_release.changelog]
150
+ exclude_commit_patterns = [
151
+ '''chore(?:\([^)]*?\))?: .+''',
152
+ '''ci(?:\([^)]*?\))?: .+''',
153
+ '''refactor(?:\([^)]*?\))?: .+''',
154
+ '''style(?:\([^)]*?\))?: .+''',
155
+ '''test(?:\([^)]*?\))?: .+''',
156
+ '''build\((?!deps\): .+)''',
157
+ '''Merged? .*''',
158
+ '''Initial [Cc]ommit.*''', # codespell:ignore
159
+ ]
160
+
161
+ [tool.semantic_release.changelog.environment]
162
+ keep_trailing_newline = true
163
+
164
+ [tool.semantic_release.branches.main]
165
+ match = "main"
166
+
167
+ [tool.semantic_release.branches.noop]
168
+ match = "(?!main$)"
169
+ prerelease = true
@@ -0,0 +1 @@
1
+ __version__ = "0.0.0"
@@ -0,0 +1,77 @@
1
+ """CLI entry point for Poks package manager."""
2
+
3
+ import sys
4
+ from pathlib import Path
5
+ from typing import Annotated
6
+
7
+ import typer
8
+ from py_app_dev.core.exceptions import UserNotificationException
9
+ from py_app_dev.core.logging import logger, setup_logger, time_it
10
+
11
+ from poks import __version__
12
+ from poks.poks import Poks
13
+
14
+ package_name = "poks"
15
+ DEFAULT_ROOT_DIR = Path.home() / ".poks"
16
+
17
+ app = typer.Typer(
18
+ name=package_name,
19
+ help="A lightweight archive downloader for pre-build binary dependencies.",
20
+ no_args_is_help=True,
21
+ add_completion=False,
22
+ )
23
+
24
+
25
+ @app.callback(invoke_without_command=True)
26
+ def version(
27
+ version: bool = typer.Option(None, "--version", "-v", is_eager=True, help="Show version and exit."),
28
+ ) -> None:
29
+ if version:
30
+ typer.echo(f"{package_name} {__version__}")
31
+ raise typer.Exit()
32
+
33
+
34
+ @app.command(help="Install apps from configuration file.")
35
+ @time_it("install")
36
+ def install(
37
+ config_file: Annotated[Path, typer.Option("-c", "--config", help="Path to poks.json configuration file.")],
38
+ root_dir: Annotated[Path, typer.Option("--root", help="Root directory for Poks.")] = DEFAULT_ROOT_DIR,
39
+ ) -> None:
40
+ poks = Poks(root_dir=root_dir)
41
+ poks.install(config_file)
42
+
43
+
44
+ @app.command(help="Uninstall apps.")
45
+ @time_it("uninstall")
46
+ def uninstall(
47
+ app_spec: Annotated[str | None, typer.Argument(help="App to uninstall. Format: name or name@version")] = None,
48
+ all_apps: Annotated[bool, typer.Option("--all", help="Uninstall all apps.")] = False,
49
+ root_dir: Annotated[Path, typer.Option("--root", help="Root directory for Poks.")] = DEFAULT_ROOT_DIR,
50
+ ) -> None:
51
+ poks = Poks(root_dir=root_dir)
52
+
53
+ if all_apps:
54
+ poks.uninstall(all_apps=True)
55
+ elif app_spec:
56
+ if "@" in app_spec:
57
+ name, version = app_spec.split("@", 1)
58
+ poks.uninstall(app_name=name, version=version)
59
+ else:
60
+ poks.uninstall(app_name=app_spec)
61
+ else:
62
+ logger.error("Specify an app to uninstall or use --all")
63
+ raise typer.Exit(1)
64
+
65
+
66
+ def main() -> int:
67
+ try:
68
+ setup_logger()
69
+ app()
70
+ return 0
71
+ except UserNotificationException as e:
72
+ logger.error(f"{e}")
73
+ return 1
74
+
75
+
76
+ if __name__ == "__main__":
77
+ sys.exit(main())
@@ -0,0 +1,56 @@
1
+ """Poks package manager core class."""
2
+
3
+ from pathlib import Path
4
+
5
+ from py_app_dev.core.logging import logger
6
+
7
+
8
+ class Poks:
9
+ """Cross-platform package manager for developer tools."""
10
+
11
+ def __init__(self, root_dir: Path) -> None:
12
+ """
13
+ Initialize Poks with a root directory.
14
+
15
+ Args:
16
+ root_dir: Root directory for Poks (apps, buckets, cache).
17
+
18
+ """
19
+ self.root_dir = root_dir
20
+ self.apps_dir = root_dir / "apps"
21
+ self.buckets_dir = root_dir / "buckets"
22
+ self.cache_dir = root_dir / "cache"
23
+
24
+ def install(self, config_file: Path) -> dict[str, str]:
25
+ """
26
+ Install apps from a configuration file.
27
+
28
+ Args:
29
+ config_file: Path to poks.json configuration file.
30
+
31
+ Returns:
32
+ Dictionary of environment variable updates.
33
+
34
+ """
35
+ logger.info(f"Installing apps from {config_file}")
36
+ # TODO: Implement actual installation logic
37
+ return {}
38
+
39
+ def uninstall(self, app_name: str | None = None, version: str | None = None, all_apps: bool = False) -> None:
40
+ """
41
+ Uninstall apps.
42
+
43
+ Args:
44
+ app_name: Name of the app to uninstall. If None and all_apps is True, uninstalls everything.
45
+ version: Specific version to uninstall. If None, uninstalls all versions of the app.
46
+ all_apps: If True, uninstalls all apps.
47
+
48
+ """
49
+ if all_apps:
50
+ logger.info("Uninstalling all apps")
51
+ elif app_name and version:
52
+ logger.info(f"Uninstalling {app_name}@{version}")
53
+ elif app_name:
54
+ logger.info(f"Uninstalling all versions of {app_name}")
55
+ else:
56
+ logger.warning("Nothing to uninstall. Specify an app name or use --all.")
File without changes