diff --git a/pyproject.toml b/pyproject.toml index 6d184cbfe4..9f2a2d91d9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,6 +83,7 @@ include = [ "src/dstack/plugins", "src/dstack/_internal/server", "src/dstack/_internal/core/services", + "src/dstack/_internal/cli/commands", "src/dstack/_internal/cli/services/configurators", ] ignore = [ diff --git a/src/dstack/_internal/cli/commands/__init__.py b/src/dstack/_internal/cli/commands/__init__.py index 7a6f6eb61a..48ee1148e2 100644 --- a/src/dstack/_internal/cli/commands/__init__.py +++ b/src/dstack/_internal/cli/commands/__init__.py @@ -54,7 +54,7 @@ def _command(self, args: argparse.Namespace): class APIBaseCommand(BaseCommand): - api: Client = None + api: Client def _register(self): self._parser.add_argument( @@ -62,7 +62,7 @@ def _register(self): help="The name of the project. Defaults to [code]$DSTACK_PROJECT[/]", metavar="NAME", default=os.getenv("DSTACK_PROJECT"), - ).completer = ProjectNameCompleter() + ).completer = ProjectNameCompleter() # type: ignore[attr-defined] def _command(self, args: argparse.Namespace): configure_logging() diff --git a/src/dstack/_internal/cli/commands/apply.py b/src/dstack/_internal/cli/commands/apply.py index caf6bf93e8..3ab26c5f4d 100644 --- a/src/dstack/_internal/cli/commands/apply.py +++ b/src/dstack/_internal/cli/commands/apply.py @@ -1,7 +1,7 @@ import argparse from pathlib import Path -from argcomplete import FilesCompleter +from argcomplete import FilesCompleter # type: ignore[attr-defined] from dstack._internal.cli.commands import APIBaseCommand from dstack._internal.cli.services.configurators import ( @@ -48,7 +48,7 @@ def _register(self): " Defaults to [code]$PWD/.dstack.yml[/]" ), dest="configuration_file", - ).completer = FilesCompleter(allowednames=["*.yml", "*.yaml"]) + ).completer = FilesCompleter(allowednames=["*.yml", "*.yaml"]) # type: ignore[attr-defined] self._parser.add_argument( "-y", "--yes", diff --git a/src/dstack/_internal/cli/commands/attach.py b/src/dstack/_internal/cli/commands/attach.py index b0d414a8c7..367e65232c 100644 --- a/src/dstack/_internal/cli/commands/attach.py +++ b/src/dstack/_internal/cli/commands/attach.py @@ -61,7 +61,7 @@ def _register(self): type=int, default=0, ) - self._parser.add_argument("run_name").completer = RunNameCompleter() + self._parser.add_argument("run_name").completer = RunNameCompleter() # type: ignore[attr-defined] def _command(self, args: argparse.Namespace): super()._command(args) diff --git a/src/dstack/_internal/cli/commands/completion.py b/src/dstack/_internal/cli/commands/completion.py index 961d2cdd9b..588a4ce091 100644 --- a/src/dstack/_internal/cli/commands/completion.py +++ b/src/dstack/_internal/cli/commands/completion.py @@ -17,4 +17,4 @@ def _register(self): def _command(self, args): super()._command(args) - print(argcomplete.shellcode(["dstack"], shell=args.shell)) + print(argcomplete.shellcode(["dstack"], shell=args.shell)) # type: ignore[attr-defined] diff --git a/src/dstack/_internal/cli/commands/delete.py b/src/dstack/_internal/cli/commands/delete.py index b651cd7a44..6d95c0dae6 100644 --- a/src/dstack/_internal/cli/commands/delete.py +++ b/src/dstack/_internal/cli/commands/delete.py @@ -1,7 +1,7 @@ import argparse from pathlib import Path -from argcomplete import FilesCompleter +from argcomplete import FilesCompleter # type: ignore[attr-defined] from dstack._internal.cli.commands import APIBaseCommand from dstack._internal.cli.services.configurators import ( @@ -24,7 +24,7 @@ def _register(self): metavar="FILE", help="The path to the configuration file. Defaults to [code]$PWD/.dstack.yml[/]", dest="configuration_file", - ).completer = FilesCompleter(allowednames=["*.yml", "*.yaml"]) + ).completer = FilesCompleter(allowednames=["*.yml", "*.yaml"]) # type: ignore[attr-defined] self._parser.add_argument( "-y", "--yes", diff --git a/src/dstack/_internal/cli/commands/fleet.py b/src/dstack/_internal/cli/commands/fleet.py index 244563e127..c6a11abc3a 100644 --- a/src/dstack/_internal/cli/commands/fleet.py +++ b/src/dstack/_internal/cli/commands/fleet.py @@ -48,7 +48,7 @@ def _register(self): delete_parser.add_argument( "name", help="The name of the fleet", - ).completer = FleetNameCompleter() + ).completer = FleetNameCompleter() # type: ignore[attr-defined] delete_parser.add_argument( "-i", "--instance", diff --git a/src/dstack/_internal/cli/commands/gateway.py b/src/dstack/_internal/cli/commands/gateway.py index 874fb89445..1a61c48856 100644 --- a/src/dstack/_internal/cli/commands/gateway.py +++ b/src/dstack/_internal/cli/commands/gateway.py @@ -68,7 +68,7 @@ def _register(self): delete_parser.set_defaults(subfunc=self._delete) delete_parser.add_argument( "name", help="The name of the gateway" - ).completer = GatewayNameCompleter() + ).completer = GatewayNameCompleter() # type: ignore[attr-defined] delete_parser.add_argument( "-y", "--yes", action="store_true", help="Don't ask for confirmation" ) @@ -79,7 +79,7 @@ def _register(self): update_parser.set_defaults(subfunc=self._update) update_parser.add_argument( "name", help="The name of the gateway" - ).completer = GatewayNameCompleter() + ).completer = GatewayNameCompleter() # type: ignore[attr-defined] update_parser.add_argument( "--set-default", action="store_true", help="Set it the default gateway for the project" ) diff --git a/src/dstack/_internal/cli/commands/logs.py b/src/dstack/_internal/cli/commands/logs.py index d1c4885f96..db3e5139ea 100644 --- a/src/dstack/_internal/cli/commands/logs.py +++ b/src/dstack/_internal/cli/commands/logs.py @@ -30,7 +30,7 @@ def _register(self): type=int, default=0, ) - self._parser.add_argument("run_name").completer = RunNameCompleter(all=True) + self._parser.add_argument("run_name").completer = RunNameCompleter(all=True) # type: ignore[attr-defined] def _command(self, args: argparse.Namespace): super()._command(args) diff --git a/src/dstack/_internal/cli/commands/metrics.py b/src/dstack/_internal/cli/commands/metrics.py index 851ed8040b..86ecda2f5f 100644 --- a/src/dstack/_internal/cli/commands/metrics.py +++ b/src/dstack/_internal/cli/commands/metrics.py @@ -26,7 +26,7 @@ class MetricsCommand(APIBaseCommand): def _register(self): super()._register() - self._parser.add_argument("run_name").completer = RunNameCompleter() + self._parser.add_argument("run_name").completer = RunNameCompleter() # type: ignore[attr-defined] self._parser.add_argument( "-w", "--watch", diff --git a/src/dstack/_internal/cli/commands/project.py b/src/dstack/_internal/cli/commands/project.py index 38e0d6fb70..2c3ea41314 100644 --- a/src/dstack/_internal/cli/commands/project.py +++ b/src/dstack/_internal/cli/commands/project.py @@ -124,8 +124,8 @@ def _list(self, args: argparse.Namespace): table.add_column("USER", style="grey58") table.add_column("DEFAULT", justify="center") - for project_name in config_manager.list_projects(): - project_config = config_manager.get_project_config(project_name) + for project_config in config_manager.list_project_configs(): + project_name = project_config.name is_default = project_name == default_project.name if default_project else False # Get username from API diff --git a/src/dstack/_internal/cli/commands/secrets.py b/src/dstack/_internal/cli/commands/secrets.py index 9d42201ed1..64a678b2d5 100644 --- a/src/dstack/_internal/cli/commands/secrets.py +++ b/src/dstack/_internal/cli/commands/secrets.py @@ -29,7 +29,7 @@ def _register(self): get_parser.add_argument( "name", help="The name of the secret", - ).completer = SecretNameCompleter() + ).completer = SecretNameCompleter() # type: ignore[attr-defined] get_parser.set_defaults(subfunc=self._get) set_parser = subparsers.add_parser( @@ -53,7 +53,7 @@ def _register(self): delete_parser.add_argument( "name", help="The name of the secret", - ).completer = SecretNameCompleter() + ).completer = SecretNameCompleter() # type: ignore[attr-defined] delete_parser.add_argument( "-y", "--yes", help="Don't ask for confirmation", action="store_true" ) diff --git a/src/dstack/_internal/cli/commands/server.py b/src/dstack/_internal/cli/commands/server.py index d742cf662f..51ece809d3 100644 --- a/src/dstack/_internal/cli/commands/server.py +++ b/src/dstack/_internal/cli/commands/server.py @@ -74,7 +74,7 @@ def _command(self, args: Namespace): uvicorn_log_level = os.getenv("DSTACK_SERVER_UVICORN_LOG_LEVEL", "ERROR").lower() reload_disabled = os.getenv("DSTACK_SERVER_RELOAD_DISABLED") is not None - uvicorn.run( + uvicorn.run( # type: ignore[unbound-variable] "dstack._internal.server.main:app", host=args.host, port=args.port, diff --git a/src/dstack/_internal/cli/commands/stop.py b/src/dstack/_internal/cli/commands/stop.py index dced8d77ea..2eaca90edc 100644 --- a/src/dstack/_internal/cli/commands/stop.py +++ b/src/dstack/_internal/cli/commands/stop.py @@ -14,7 +14,7 @@ def _register(self): super()._register() self._parser.add_argument("-x", "--abort", action="store_true") self._parser.add_argument("-y", "--yes", action="store_true") - self._parser.add_argument("run_name").completer = RunNameCompleter() + self._parser.add_argument("run_name").completer = RunNameCompleter() # type: ignore[attr-defined] def _command(self, args: argparse.Namespace): super()._command(args) diff --git a/src/dstack/_internal/cli/commands/volume.py b/src/dstack/_internal/cli/commands/volume.py index 5f7bc833ec..3f7da2e00a 100644 --- a/src/dstack/_internal/cli/commands/volume.py +++ b/src/dstack/_internal/cli/commands/volume.py @@ -48,7 +48,7 @@ def _register(self): delete_parser.add_argument( "name", help="The name of the volume", - ).completer = VolumeNameCompleter() + ).completer = VolumeNameCompleter() # type: ignore[attr-defined] delete_parser.add_argument( "-y", "--yes", help="Don't ask for confirmation", action="store_true" ) diff --git a/src/dstack/_internal/cli/services/completion.py b/src/dstack/_internal/cli/services/completion.py index ed63d82783..39ddbc1f33 100644 --- a/src/dstack/_internal/cli/services/completion.py +++ b/src/dstack/_internal/cli/services/completion.py @@ -87,5 +87,5 @@ class ProjectNameCompleter(BaseCompleter): def __call__(self, prefix: str, parsed_args: argparse.Namespace, **kwargs) -> List[str]: argcomplete.debug(f"{self.__class__.__name__}: Listing projects from ConfigManager") - projects = ConfigManager().list_projects() - return [p for p in projects if p.startswith(prefix)] + projects = ConfigManager().list_project_configs() + return [p.name for p in projects if p.name.startswith(prefix)] diff --git a/src/dstack/_internal/core/services/configs/__init__.py b/src/dstack/_internal/core/services/configs/__init__.py index a4a063cd47..6ebf7e7654 100644 --- a/src/dstack/_internal/core/services/configs/__init__.py +++ b/src/dstack/_internal/core/services/configs/__init__.py @@ -68,8 +68,8 @@ def configure_project(self, name: str, url: str, token: str, default: bool): if len(self.config.projects) == 1: self.config.projects[0].default = True - def list_projects(self): - return [project.name for project in self.config.projects] + def list_project_configs(self) -> list[ProjectConfig]: + return self.config.projects def delete_project(self, name: str): self.config.projects = [p for p in self.config.projects if p.name != name]