Added remove & add commands
All checks were successful
Test before pr merge / test-lint (pull_request) Successful in 7s
All checks were successful
Test before pr merge / test-lint (pull_request) Successful in 7s
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"name": "cpl",
|
"name": "cpl",
|
||||||
"projects": [
|
"projects": [
|
||||||
"src/cpl-core/cpl.project.json",
|
"src/cli/cpl.project.json",
|
||||||
"src/cpl-cli/cpl.project.json"
|
"src/core/cpl.project.json"
|
||||||
],
|
],
|
||||||
"defaultProject": "cpl-cli",
|
"defaultProject": "cpl-cli",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -11,11 +11,9 @@
|
|||||||
"click": "~8.3.0"
|
"click": "~8.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"black": "~25.9"
|
"black": "~25.9.0"
|
||||||
},
|
},
|
||||||
"references": [
|
"references": [],
|
||||||
"../cpl/cpl.project.json"
|
|
||||||
],
|
|
||||||
"main": "cpl/cli/main.py",
|
"main": "cpl/cli/main.py",
|
||||||
"directory": "cpl/cli"
|
"directory": "cpl/cli"
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
|
import traceback
|
||||||
|
|
||||||
import click
|
import click
|
||||||
|
|
||||||
|
from cpl.core.console import Console
|
||||||
|
|
||||||
|
|
||||||
class AliasedGroup(click.Group):
|
class AliasedGroup(click.Group):
|
||||||
def command(self, *args, **kwargs):
|
def command(self, *args, **kwargs):
|
||||||
@@ -7,6 +11,7 @@ class AliasedGroup(click.Group):
|
|||||||
|
|
||||||
def decorator(f):
|
def decorator(f):
|
||||||
cmd = super(AliasedGroup, self).command(*args, **kwargs)(f)
|
cmd = super(AliasedGroup, self).command(*args, **kwargs)(f)
|
||||||
|
cmd.callback = self._handle_errors(cmd.callback)
|
||||||
|
|
||||||
for alias in aliases:
|
for alias in aliases:
|
||||||
self.add_command(cmd, alias)
|
self.add_command(cmd, alias)
|
||||||
@@ -28,6 +33,23 @@ class AliasedGroup(click.Group):
|
|||||||
with formatter.section("Commands"):
|
with formatter.section("Commands"):
|
||||||
formatter.write_dl(commands)
|
formatter.write_dl(commands)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _handle_errors(f):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
try:
|
||||||
|
res = f(*args, **kwargs)
|
||||||
|
Console.write_line()
|
||||||
|
return res
|
||||||
|
except Exception as e:
|
||||||
|
tb = None
|
||||||
|
if "verbose" in kwargs and kwargs["verbose"]:
|
||||||
|
tb = traceback.format_exc()
|
||||||
|
Console.error(str(e), tb)
|
||||||
|
Console.write_line()
|
||||||
|
exit(-1)
|
||||||
|
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
@click.group(cls=AliasedGroup)
|
@click.group(cls=AliasedGroup)
|
||||||
def cli(): ...
|
def cli(): ...
|
||||||
|
|||||||
51
src/cli/cpl/cli/command/package/add.py
Normal file
51
src/cli/cpl/cli/command/package/add.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import click
|
||||||
|
|
||||||
|
from cpl.cli.cli import cli
|
||||||
|
from cpl.cli.model.project import Project
|
||||||
|
from cpl.cli.model.workspace import Workspace
|
||||||
|
from cpl.core.configuration import Configuration
|
||||||
|
from cpl.core.console import Console
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command("add", aliases=["a"])
|
||||||
|
@click.argument("reference", type=click.STRING, required=True)
|
||||||
|
@click.argument("target", type=click.STRING, required=True)
|
||||||
|
@click.option("--verbose", is_flag=True, help="Enable verbose output")
|
||||||
|
def add(reference: str, target: str, verbose: bool):
|
||||||
|
workspace = None
|
||||||
|
|
||||||
|
if Configuration.get("workspace_path") is not None:
|
||||||
|
workspace = Workspace.from_file(Configuration.get("workspace_path"))
|
||||||
|
|
||||||
|
reference_project = _get_project_by_name_or_path(reference, workspace)
|
||||||
|
target_project = _get_project_by_name_or_path(target, workspace)
|
||||||
|
|
||||||
|
if reference_project.name == target_project.name:
|
||||||
|
raise ValueError("Cannot add a project as a dependency to itself!")
|
||||||
|
|
||||||
|
if reference_project.path in target_project.references:
|
||||||
|
raise ValueError(f"Project '{reference_project.name}' is already a reference of '{target_project.name}'")
|
||||||
|
target_project.references.append(reference_project.path)
|
||||||
|
target_project.save()
|
||||||
|
Console.write_line(f"Added '{reference_project.name}' to '{target_project.name}' project")
|
||||||
|
|
||||||
|
|
||||||
|
def _get_project_by_name_or_path(project: str, workspace=None) -> Project:
|
||||||
|
path = Path(project)
|
||||||
|
if path.exists() and path.is_dir():
|
||||||
|
return Project.from_file(path / "cpl.project.json")
|
||||||
|
|
||||||
|
if path.exists() and path.is_file():
|
||||||
|
if not path.name.endswith("cpl.project.json"):
|
||||||
|
raise ValueError(f"File '{path}' is not a valid cpl.project.json file.")
|
||||||
|
|
||||||
|
return Project.from_file(path)
|
||||||
|
|
||||||
|
if workspace is not None:
|
||||||
|
for p in workspace.actual_projects:
|
||||||
|
if p.name == project:
|
||||||
|
return Project.from_file(Path(p.path))
|
||||||
|
|
||||||
|
raise ValueError(f"Project '{project}' not found.")
|
||||||
@@ -24,6 +24,7 @@ from cpl.core.console import Console
|
|||||||
def install(package: str, project_path: str, project_name: str, dev: bool, verbose: bool):
|
def install(package: str, project_path: str, project_name: str, dev: bool, verbose: bool):
|
||||||
project = resolve_project(Path(project_path), project_name)
|
project = resolve_project(Path(project_path), project_name)
|
||||||
if package is not None:
|
if package is not None:
|
||||||
|
Console.write_line(dev)
|
||||||
Console.write_line(f"Installing {package} to '{project.name}':")
|
Console.write_line(f"Installing {package} to '{project.name}':")
|
||||||
try:
|
try:
|
||||||
Pip.command("install", package, verbose=verbose, path=project_path)
|
Pip.command("install", package, verbose=verbose, path=project_path)
|
||||||
@@ -36,7 +37,9 @@ def install(package: str, project_path: str, project_name: str, dev: bool, verbo
|
|||||||
Console.error(f"Package '{package_name}' not found after installation.")
|
Console.error(f"Package '{package_name}' not found after installation.")
|
||||||
return
|
return
|
||||||
|
|
||||||
project.dependencies[package_name] = Pip.apply_prefix(installed_version, Pip.get_package_full_version(package))
|
deps = project.dependencies if not dev else project.dev_dependencies
|
||||||
|
deps[package_name] = Pip.apply_prefix(installed_version, Pip.get_package_full_version(package))
|
||||||
|
|
||||||
project.save()
|
project.save()
|
||||||
Console.write_line(f"Added {package_name}~{installed_version} to project dependencies.")
|
Console.write_line(f"Added {package_name}~{installed_version} to project dependencies.")
|
||||||
return
|
return
|
||||||
|
|||||||
52
src/cli/cpl/cli/command/package/remove.py
Normal file
52
src/cli/cpl/cli/command/package/remove.py
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import click
|
||||||
|
|
||||||
|
from cpl.cli.cli import cli
|
||||||
|
from cpl.cli.model.project import Project
|
||||||
|
from cpl.cli.model.workspace import Workspace
|
||||||
|
from cpl.core.configuration import Configuration
|
||||||
|
from cpl.core.console import Console
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command("remove", aliases=["rm"])
|
||||||
|
@click.argument("reference", type=click.STRING, required=True)
|
||||||
|
@click.argument("target", type=click.STRING, required=True)
|
||||||
|
@click.option("--verbose", is_flag=True, help="Enable verbose output")
|
||||||
|
def remove(reference: str, target: str, verbose: bool):
|
||||||
|
workspace = None
|
||||||
|
|
||||||
|
if Configuration.get("workspace_path") is not None:
|
||||||
|
workspace = Workspace.from_file(Configuration.get("workspace_path"))
|
||||||
|
|
||||||
|
reference_project = _get_project_by_name_or_path(reference, workspace)
|
||||||
|
target_project = _get_project_by_name_or_path(target, workspace)
|
||||||
|
|
||||||
|
if reference_project.name == target_project.name:
|
||||||
|
raise ValueError("Cannot add a project as a dependency to itself!")
|
||||||
|
|
||||||
|
if reference_project.path not in target_project.references:
|
||||||
|
raise ValueError(f"Project '{reference_project.name}' isn't a reference of '{target_project.name}'")
|
||||||
|
|
||||||
|
target_project.references.remove(reference_project.path)
|
||||||
|
target_project.save()
|
||||||
|
Console.write_line(f"Removed '{reference_project.name}' from '{target_project.name}' project")
|
||||||
|
|
||||||
|
|
||||||
|
def _get_project_by_name_or_path(project: str, workspace=None) -> Project:
|
||||||
|
path = Path(project)
|
||||||
|
if path.exists() and path.is_dir():
|
||||||
|
return Project.from_file(path / "cpl.project.json")
|
||||||
|
|
||||||
|
if path.exists() and path.is_file():
|
||||||
|
if not path.name.endswith("cpl.project.json"):
|
||||||
|
raise ValueError(f"File '{path}' is not a valid cpl.project.json file.")
|
||||||
|
|
||||||
|
return Project.from_file(path)
|
||||||
|
|
||||||
|
if workspace is not None:
|
||||||
|
for p in workspace.actual_projects:
|
||||||
|
if p.name == project:
|
||||||
|
return Project.from_file(Path(p.path))
|
||||||
|
|
||||||
|
raise ValueError(f"Project '{project}' not found.")
|
||||||
@@ -29,7 +29,7 @@ def uninstall(package: str, project_path: str, project_name: str, dev: bool, ver
|
|||||||
deps = project.dependencies if not dev else project.dev_dependencies
|
deps = project.dependencies if not dev else project.dev_dependencies
|
||||||
|
|
||||||
try:
|
try:
|
||||||
Pip.command("install", package, verbose=verbose, path=project_path)
|
Pip.command("uninstall -y", package, verbose=verbose, path=project_path)
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
Console.error(f"Failed to uninstall {package}: exit code {e.returncode}")
|
Console.error(f"Failed to uninstall {package}: exit code {e.returncode}")
|
||||||
return
|
return
|
||||||
@@ -38,3 +38,6 @@ def uninstall(package: str, project_path: str, project_name: str, dev: bool, ver
|
|||||||
del deps[package]
|
del deps[package]
|
||||||
project.save()
|
project.save()
|
||||||
Console.write_line(f"Removed {package} from project dependencies.")
|
Console.write_line(f"Removed {package} from project dependencies.")
|
||||||
|
return
|
||||||
|
|
||||||
|
Console.write_line(f"Package {package} was not found in project dependencies.")
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ import os
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from cpl.cli.cli import cli
|
from cpl.cli.cli import cli
|
||||||
from cpl.cli.command.init import init
|
from cpl.cli.command.package.remove import remove
|
||||||
from cpl.cli.command.install import install
|
from cpl.cli.command.package.add import add
|
||||||
from cpl.cli.command.uninstall import uninstall
|
from cpl.cli.command.structure.init import init
|
||||||
from cpl.cli.command.update import update
|
from cpl.cli.command.package.install import install
|
||||||
|
from cpl.cli.command.package.uninstall import uninstall
|
||||||
|
from cpl.cli.command.package.update import update
|
||||||
from cpl.cli.command.version import version
|
from cpl.cli.command.version import version
|
||||||
from cpl.cli.model.workspace import Workspace
|
from cpl.cli.model.workspace import Workspace
|
||||||
from cpl.cli.utils.custom_command import script_command
|
from cpl.cli.utils.custom_command import script_command
|
||||||
@@ -54,8 +56,8 @@ def configure():
|
|||||||
cli.add_command(install)
|
cli.add_command(install)
|
||||||
cli.add_command(uninstall)
|
cli.add_command(uninstall)
|
||||||
cli.add_command(update)
|
cli.add_command(update)
|
||||||
# cli.add_command(add)
|
cli.add_command(add)
|
||||||
# cli.add_command(remove)
|
cli.add_command(remove)
|
||||||
|
|
||||||
# run
|
# run
|
||||||
# cli.add_command(run)
|
# cli.add_command(run)
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class CPLStructureModel:
|
|||||||
kwargs: Dict[str, Any] = {}
|
kwargs: Dict[str, Any] = {}
|
||||||
for name, param in list(sig.parameters.items())[1:]:
|
for name, param in list(sig.parameters.items())[1:]:
|
||||||
if name == "path":
|
if name == "path":
|
||||||
kwargs[name] = path
|
kwargs[name] = str(path)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if name in data:
|
if name in data:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from typing import Optional, List, Dict
|
from typing import Optional, List, Dict
|
||||||
|
|
||||||
from cpl.cli.model.cpl_structure_model import CPLStructureModel
|
from cpl.cli.model.cpl_structure_model import CPLStructureModel
|
||||||
|
from cpl.cli.model.project import Project
|
||||||
|
|
||||||
|
|
||||||
class Workspace(CPLStructureModel):
|
class Workspace(CPLStructureModel):
|
||||||
@@ -45,6 +46,10 @@ class Workspace(CPLStructureModel):
|
|||||||
def projects(self, value: List[str]):
|
def projects(self, value: List[str]):
|
||||||
self._projects = self._require_list_of_str(value, "projects")
|
self._projects = self._require_list_of_str(value, "projects")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def actual_projects(self) -> List[Project]:
|
||||||
|
return [Project.from_file(p) for p in self._projects]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def default_project(self) -> Optional[str]:
|
def default_project(self) -> Optional[str]:
|
||||||
return self._default_project
|
return self._default_project
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import json
|
import json
|
||||||
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from cpl.cli.model.project import Project
|
from cpl.cli.model.project import Project
|
||||||
|
|||||||
12
src/cli/run
Executable file
12
src/cli/run
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
cd ../
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
|
export PYTHONPATH="$ROOT_DIR/core:$ROOT_DIR/cli:$PYTHONPATH"
|
||||||
|
|
||||||
|
old_dir="$(pwd)"
|
||||||
|
cd ../
|
||||||
|
python -m cpl.cli.main "$@"
|
||||||
|
cd "$old_dir"
|
||||||
Reference in New Issue
Block a user