feat(installer): add support for installing from wheel

This allows us to easily test the installer without needing the desired version to be published on PyPI:
```sh
python3 installer/lib/main.py --wheel installer/dist/InvokeAI-4.0.0rc6-py3-none-any.whl
```

A warning message and confirmation are displayed when the arg is used.

The rest of the installer is unchanged.
This commit is contained in:
psychedelicious 2024-03-26 14:24:06 +11:00
parent eb2a1993f1
commit dfc08bd964
3 changed files with 56 additions and 10 deletions

View File

@ -5,6 +5,7 @@ InvokeAI installer script
import os import os
import platform import platform
import re
import shutil import shutil
import subprocess import subprocess
import sys import sys
@ -22,6 +23,15 @@ ARCH = platform.uname().machine
VERSION = "latest" VERSION = "latest"
def get_version_from_wheel_filename(wheel_filename: str) -> str:
match = re.search(r"-(\d+\.\d+\.\d+)", wheel_filename)
if match:
version = match.group(1)
return version
else:
raise ValueError(f"Could not extract version from wheel filename: {wheel_filename}")
class Installer: class Installer:
""" """
Deploys an InvokeAI installation into a given path Deploys an InvokeAI installation into a given path
@ -111,6 +121,7 @@ class Installer:
yes_to_all: bool = False, yes_to_all: bool = False,
version: Optional[str] = None, version: Optional[str] = None,
find_links: Optional[str] = None, find_links: Optional[str] = None,
wheel: Optional[Path] = None,
) -> None: ) -> None:
""" """
Install the InvokeAI application into the given runtime path Install the InvokeAI application into the given runtime path
@ -127,8 +138,11 @@ class Installer:
import messages import messages
if wheel:
messages.installing_from_wheel(wheel.name)
version = get_version_from_wheel_filename(wheel.name)
else:
messages.welcome(self.available_releases) messages.welcome(self.available_releases)
version = messages.choose_version(self.available_releases) version = messages.choose_version(self.available_releases)
auto_dest = Path(os.environ.get("INVOKEAI_ROOT", root)).expanduser().resolve() auto_dest = Path(os.environ.get("INVOKEAI_ROOT", root)).expanduser().resolve()
@ -144,11 +158,7 @@ class Installer:
# install dependencies and the InvokeAI application # install dependencies and the InvokeAI application
(extra_index_url, optional_modules) = get_torch_source() if not yes_to_all else (None, None) (extra_index_url, optional_modules) = get_torch_source() if not yes_to_all else (None, None)
self.instance.install( self.instance.install(extra_index_url, optional_modules, find_links, wheel)
extra_index_url,
optional_modules,
find_links,
)
# install the launch/update scripts into the runtime directory # install the launch/update scripts into the runtime directory
self.instance.install_user_scripts() self.instance.install_user_scripts()
@ -187,6 +197,7 @@ class InvokeAiInstance:
extra_index_url: Optional[str] = None, extra_index_url: Optional[str] = None,
optional_modules: Optional[str] = None, optional_modules: Optional[str] = None,
find_links: Optional[str] = None, find_links: Optional[str] = None,
wheel: Optional[Path] = None,
): ):
""" """
Install the package from PyPi. Install the package from PyPi.
@ -231,12 +242,12 @@ class InvokeAiInstance:
"--require-virtualenv", "--require-virtualenv",
"--force-reinstall", "--force-reinstall",
"--use-pep517", "--use-pep517",
str(src), str(src) if not wheel else str(wheel),
"--find-links" if find_links is not None else None, "--find-links" if find_links is not None else None,
find_links, find_links,
"--extra-index-url" if extra_index_url is not None else None, "--extra-index-url" if extra_index_url is not None else None,
extra_index_url, extra_index_url,
pre_flag, pre_flag if not wheel else None,
] ]
try: try:

View File

@ -44,6 +44,14 @@ if __name__ == "__main__":
default=None, default=None,
) )
parser.add_argument(
"--wheel",
dest="wheel",
help="Specifies a wheel for the InvokeAI package. Used for troubleshooting or testing prereleases.",
type=Path,
default=None,
)
args = parser.parse_args() args = parser.parse_args()
inst = Installer() inst = Installer()

View File

@ -73,6 +73,33 @@ def welcome(available_releases: tuple[list[str], list[str]] | None = None) -> No
console.line() console.line()
def installing_from_wheel(wheel_filename: str) -> None:
"""Display a message about installing from a wheel"""
@group()
def text():
yield Text.from_markup(f"You are installing from a wheel file: [bold]{wheel_filename}\n")
yield Text.from_markup(
"[bold orange3]If you are not sure why you are doing this, you should cancel and install InvokeAI normally."
)
console.print(
Panel(
title="Installing from Wheel",
renderable=text(),
box=box.DOUBLE,
expand=True,
padding=(1, 2),
)
)
should_proceed = Confirm.ask("Do you want to proceed?")
if not should_proceed:
console.print("Installation cancelled.")
exit()
def choose_version(available_releases: tuple[list[str], list[str]] | None = None) -> str: def choose_version(available_releases: tuple[list[str], list[str]] | None = None) -> str:
""" """
Prompt the user to choose an Invoke version to install Prompt the user to choose an Invoke version to install