mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
(installer) support both pip and source install; no longer support installing from a downloaded release .zip
This commit is contained in:
parent
2ff47cdecf
commit
d209dab881
@ -1 +0,0 @@
|
|||||||
recursive-include ldm/invoke/config/configs *
|
|
@ -9,7 +9,7 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
import venv
|
import venv
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from tempfile import TemporaryDirectory, TemporaryFile
|
from tempfile import TemporaryDirectory
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
SUPPORTED_PYTHON = ">=3.9.0,<3.11"
|
SUPPORTED_PYTHON = ">=3.9.0,<3.11"
|
||||||
@ -26,8 +26,6 @@ FF_VENV_IN_RUNTIME = True
|
|||||||
# Install the wheel from pypi
|
# Install the wheel from pypi
|
||||||
FF_USE_WHEEL = False
|
FF_USE_WHEEL = False
|
||||||
|
|
||||||
INVOKE_AI_SRC = f"https://github.com/invoke-ai/InvokeAI/archive/refs/tags/${VERSION}.zip"
|
|
||||||
|
|
||||||
|
|
||||||
class Installer:
|
class Installer:
|
||||||
"""
|
"""
|
||||||
@ -67,12 +65,11 @@ class Installer:
|
|||||||
# and a stack trace.
|
# and a stack trace.
|
||||||
# `ignore_cleanup_errors` was only added in Python 3.10
|
# `ignore_cleanup_errors` was only added in Python 3.10
|
||||||
# users of Python 3.9 will see a gnarly stack trace on installer exit
|
# users of Python 3.9 will see a gnarly stack trace on installer exit
|
||||||
if OS == "Windows" and int(platform.python_version_tuple()[1])>=10:
|
if OS == "Windows" and int(platform.python_version_tuple()[1]) >= 10:
|
||||||
venv_dir = TemporaryDirectory(prefix="invokeai-installer-", ignore_cleanup_errors=True)
|
venv_dir = TemporaryDirectory(prefix="invokeai-installer-", ignore_cleanup_errors=True)
|
||||||
else:
|
else:
|
||||||
venv_dir = TemporaryDirectory(prefix="invokeai-installer-")
|
venv_dir = TemporaryDirectory(prefix="invokeai-installer-")
|
||||||
|
|
||||||
|
|
||||||
venv.create(venv_dir.name, with_pip=True)
|
venv.create(venv_dir.name, with_pip=True)
|
||||||
self.venv_dir = venv_dir
|
self.venv_dir = venv_dir
|
||||||
add_venv_site(Path(venv_dir.name))
|
add_venv_site(Path(venv_dir.name))
|
||||||
@ -133,13 +130,6 @@ class Installer:
|
|||||||
venv.create(venv_dir, with_pip=True)
|
venv.create(venv_dir, with_pip=True)
|
||||||
return venv_dir
|
return venv_dir
|
||||||
|
|
||||||
def get_payload():
|
|
||||||
"""
|
|
||||||
Obtain the InvokeAI installation payload
|
|
||||||
"""
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
def install(self, root: str = "~/invokeai", version: str = "latest", yes_to_all=False) -> None:
|
def install(self, root: str = "~/invokeai", version: str = "latest", yes_to_all=False) -> None:
|
||||||
"""
|
"""
|
||||||
Install the InvokeAI application into the given runtime path
|
Install the InvokeAI application into the given runtime path
|
||||||
@ -161,14 +151,11 @@ class Installer:
|
|||||||
# create the venv for the app
|
# create the venv for the app
|
||||||
self.venv = self.app_venv()
|
self.venv = self.app_venv()
|
||||||
|
|
||||||
self.instance = InvokeAiInstance(runtime=self.dest, venv=self.venv)
|
self.instance = InvokeAiInstance(runtime=self.dest, venv=self.venv, version=version)
|
||||||
|
|
||||||
# install dependencies and the InvokeAI application
|
# install dependencies and the InvokeAI application
|
||||||
extra_index_url=get_torch_source() if not yes_to_all else None
|
|
||||||
if FF_USE_WHEEL:
|
self.instance.install(extra_index_url = get_torch_source() if not yes_to_all else None)
|
||||||
self.instance.deploy_wheel(extra_index_url)
|
|
||||||
else:
|
|
||||||
self.instance.deploy_src(extra_index_url)
|
|
||||||
|
|
||||||
# run through the configuration flow
|
# run through the configuration flow
|
||||||
self.instance.configure()
|
self.instance.configure()
|
||||||
@ -184,11 +171,12 @@ class InvokeAiInstance:
|
|||||||
A single runtime directory *may* be shared by multiple virtual environments, though this isn't currently tested or supported.
|
A single runtime directory *may* be shared by multiple virtual environments, though this isn't currently tested or supported.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, runtime: Path, venv: Path) -> None:
|
def __init__(self, runtime: Path, venv: Path, version: str) -> None:
|
||||||
|
|
||||||
self.runtime = runtime
|
self.runtime = runtime
|
||||||
self.venv = venv
|
self.venv = venv
|
||||||
self.pip = get_venv_pip(venv)
|
self.pip = get_venv_pip(venv)
|
||||||
|
self.version = version
|
||||||
|
|
||||||
add_venv_site(venv)
|
add_venv_site(venv)
|
||||||
os.environ["INVOKEAI_ROOT"] = str(self.runtime.expanduser().resolve())
|
os.environ["INVOKEAI_ROOT"] = str(self.runtime.expanduser().resolve())
|
||||||
@ -204,75 +192,23 @@ class InvokeAiInstance:
|
|||||||
|
|
||||||
return (self.runtime, self.venv)
|
return (self.runtime, self.venv)
|
||||||
|
|
||||||
def deploy_src(self, extra_index_url=None):
|
def install(self, extra_index_url=None):
|
||||||
"""
|
"""
|
||||||
Install packages with pip ("source" installer)
|
Install this instance, including depenencies and the app itself
|
||||||
|
|
||||||
:param extra_index_url: the "--extra-index-url ..." line for pip to look in extra indexes.
|
:param extra_index_url: the "--extra-index-url ..." line for pip to look in extra indexes.
|
||||||
:type extra_index_url: str
|
:type extra_index_url: str
|
||||||
"""
|
"""
|
||||||
|
|
||||||
### TODO: pull the source archive from Github like the current installer does?
|
|
||||||
### Alternatively, decide if this should just be used to perform an editable install
|
|
||||||
|
|
||||||
import messages
|
import messages
|
||||||
from plumbum import FG, local
|
|
||||||
|
|
||||||
# pre-installing Torch because this is the most reliable way to ensure
|
# install torch first to ensure the correct version gets installed.
|
||||||
# the correct version gets installed.
|
# works with either source or wheel install with negligible impact on installation times.
|
||||||
# this works with either source or wheel install and has
|
|
||||||
# negligible impact on installation times.
|
|
||||||
# this is only necessary for the source installer.
|
|
||||||
messages.simple_banner("Installing PyTorch :fire:")
|
messages.simple_banner("Installing PyTorch :fire:")
|
||||||
self.install_torch(extra_index_url)
|
self.install_torch(extra_index_url)
|
||||||
|
|
||||||
messages.simple_banner("Installing InvokeAI base dependencies :rocket:")
|
|
||||||
extra_index_url_arg = "--extra-index-url" if extra_index_url is not None else None
|
|
||||||
|
|
||||||
pip = local[self.pip]
|
|
||||||
|
|
||||||
(
|
|
||||||
pip[
|
|
||||||
"install",
|
|
||||||
"--require-virtualenv",
|
|
||||||
"-r",
|
|
||||||
(Path(__file__).parents[1] / "environments-and-requirements/requirements-base.txt")
|
|
||||||
.expanduser()
|
|
||||||
.resolve(),
|
|
||||||
"--use-pep517",
|
|
||||||
extra_index_url_arg,
|
|
||||||
extra_index_url,
|
|
||||||
]
|
|
||||||
& FG
|
|
||||||
)
|
|
||||||
|
|
||||||
def deploy_wheel(self, extra_index_url=None):
|
|
||||||
"""
|
|
||||||
Use 'pip' to install packages with from PyPi and optionally other indexes ("wheel" installer)
|
|
||||||
|
|
||||||
:param extra_index_url: the "--extra-index-url ..." line for pip to look in extra indexes.
|
|
||||||
:type extra_index_url: str
|
|
||||||
"""
|
|
||||||
|
|
||||||
import messages
|
|
||||||
from plumbum import FG, local
|
|
||||||
|
|
||||||
messages.simple_banner("Installing the InvokeAI Application :art:")
|
messages.simple_banner("Installing the InvokeAI Application :art:")
|
||||||
extra_index_url_arg = "--extra-index-url" if extra_index_url is not None else None
|
self.install_app(extra_index_url)
|
||||||
|
|
||||||
pip = local[self.pip]
|
|
||||||
|
|
||||||
(
|
|
||||||
pip[
|
|
||||||
"install",
|
|
||||||
"--require-virtualenv",
|
|
||||||
"--use-pep517",
|
|
||||||
"invokeai",
|
|
||||||
extra_index_url_arg,
|
|
||||||
extra_index_url,
|
|
||||||
]
|
|
||||||
& FG
|
|
||||||
)
|
|
||||||
|
|
||||||
def install_torch(self, extra_index_url=None):
|
def install_torch(self, extra_index_url=None):
|
||||||
"""
|
"""
|
||||||
@ -281,8 +217,6 @@ class InvokeAiInstance:
|
|||||||
|
|
||||||
from plumbum import FG, local
|
from plumbum import FG, local
|
||||||
|
|
||||||
extra_index_url_arg = "--extra-index-url" if extra_index_url is not None else None
|
|
||||||
|
|
||||||
pip = local[self.pip]
|
pip = local[self.pip]
|
||||||
|
|
||||||
(
|
(
|
||||||
@ -291,12 +225,52 @@ class InvokeAiInstance:
|
|||||||
"--require-virtualenv",
|
"--require-virtualenv",
|
||||||
"torch",
|
"torch",
|
||||||
"torchvision",
|
"torchvision",
|
||||||
extra_index_url_arg,
|
"--extra-index-url" if extra_index_url is not None else None,
|
||||||
extra_index_url,
|
extra_index_url,
|
||||||
]
|
]
|
||||||
& FG
|
& FG
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def install_app(self, extra_index_url=None):
|
||||||
|
"""
|
||||||
|
Install the application with pip.
|
||||||
|
Supports installation from PyPi or from a local source directory.
|
||||||
|
|
||||||
|
:param extra_index_url: the "--extra-index-url ..." line for pip to look in extra indexes.
|
||||||
|
:type extra_index_url: str
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.version == "pre":
|
||||||
|
version = None
|
||||||
|
pre = "--pre"
|
||||||
|
else:
|
||||||
|
version = self.version
|
||||||
|
pre = None
|
||||||
|
|
||||||
|
if FF_USE_WHEEL:
|
||||||
|
src = f"invokeai=={version}" if version is not None else "invokeai"
|
||||||
|
else:
|
||||||
|
# this makes an assumption about the location of the installer package in the source tree
|
||||||
|
src = Path(__file__).parents[1].expanduser().resolve()
|
||||||
|
|
||||||
|
import messages
|
||||||
|
from plumbum import FG, local
|
||||||
|
|
||||||
|
pip = local[self.pip]
|
||||||
|
|
||||||
|
(
|
||||||
|
pip[
|
||||||
|
"install",
|
||||||
|
"--require-virtualenv",
|
||||||
|
"--use-pep517",
|
||||||
|
src,
|
||||||
|
"--extra-index-url" if extra_index_url is not None else None,
|
||||||
|
extra_index_url,
|
||||||
|
pre,
|
||||||
|
]
|
||||||
|
& FG
|
||||||
|
)
|
||||||
|
|
||||||
def configure(self):
|
def configure(self):
|
||||||
"""
|
"""
|
||||||
Configure the InvokeAI runtime directory
|
Configure the InvokeAI runtime directory
|
||||||
@ -318,12 +292,12 @@ class InvokeAiInstance:
|
|||||||
Copy the launch and update scripts to the runtime dir
|
Copy the launch and update scripts to the runtime dir
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ext = 'bat' if OS == 'Windows' else 'sh'
|
ext = "bat" if OS == "Windows" else "sh"
|
||||||
|
|
||||||
for script in ["invoke", "update"]:
|
for script in ["invoke", "update"]:
|
||||||
src = Path(__file__).parent / "templates" / f"{script}.{ext}.in"
|
src = Path(__file__).parent / "templates" / f"{script}.{ext}.in"
|
||||||
dest = self.runtime / f"{script}.{ext}"
|
dest = self.runtime / f"{script}.{ext}"
|
||||||
shutil.copy (src, dest)
|
shutil.copy(src, dest)
|
||||||
os.chmod(dest, 0o0755)
|
os.chmod(dest, 0o0755)
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
@ -349,7 +323,7 @@ def get_venv_pip(venv_path: Path) -> str:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
pip = "Scripts\pip.exe" if OS == "Windows" else "bin/pip"
|
pip = "Scripts\pip.exe" if OS == "Windows" else "bin/pip"
|
||||||
return str(venv_path.absolute() / pip)
|
return str(venv_path.expanduser().resolve() / pip)
|
||||||
|
|
||||||
|
|
||||||
def add_venv_site(venv_path: Path) -> None:
|
def add_venv_site(venv_path: Path) -> None:
|
||||||
@ -363,7 +337,7 @@ def add_venv_site(venv_path: Path) -> None:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
lib = "Lib" if OS == "Windows" else f"lib/python{sys.version_info.major}.{sys.version_info.minor}"
|
lib = "Lib" if OS == "Windows" else f"lib/python{sys.version_info.major}.{sys.version_info.minor}"
|
||||||
sys.path.append(str(Path(venv_path, lib, "site-packages").absolute()))
|
sys.path.append(str(Path(venv_path, lib, "site-packages").expanduser().resolve()))
|
||||||
|
|
||||||
|
|
||||||
def get_torch_source() -> Union[str, None]:
|
def get_torch_source() -> Union[str, None]:
|
||||||
|
@ -26,6 +26,13 @@ if __name__ == "__main__":
|
|||||||
default=False,
|
default=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"--version",
|
||||||
|
dest="version",
|
||||||
|
help="Version of InvokeAI to install. Default to the latest stable release. A special 'pre' value will install the latest published pre-release version.",
|
||||||
|
default=None,
|
||||||
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
inst = Installer()
|
inst = Installer()
|
||||||
|
Loading…
Reference in New Issue
Block a user