mirror of
https://github.com/zebrajr/faceswap.git
synced 2026-01-15 12:15:15 +00:00
Merge branch 'master' into plaidml
This commit is contained in:
@@ -135,10 +135,11 @@ A desktop shortcut can be added to easily launch straight into the faceswap GUI:
|
||||
|
||||
## Updating faceswap
|
||||
It's good to keep faceswap up to date as new features are added and bugs are fixed. To do so:
|
||||
- If using the GUI you can go to the Tools Menu and select "Check for Updates...". This will update Faceswap to the latest code and update your dependencies.
|
||||
- If you are not already in your virtual environment follow [these steps](#entering-your-virtual-environment)
|
||||
- Enter the faceswap folder: `cd faceswap`
|
||||
- Enter the following `git pull --all`
|
||||
- Once the latest version has downloaded, make sure your requirements are up to date: `pip install --upgrade -r requirements.txt`
|
||||
- Once the latest version has downloaded, make sure your dependencies are up to date. There is a script to help with this: `python update_deps.py`
|
||||
|
||||
# General Install Guide
|
||||
## Installing dependencies
|
||||
|
||||
@@ -13,6 +13,7 @@ from subprocess import Popen, PIPE, STDOUT
|
||||
from lib.multithreading import MultiThread
|
||||
from lib.Serializer import JSONSerializer
|
||||
|
||||
import update_deps
|
||||
from .utils import get_config
|
||||
from .popup_configure import popup_config
|
||||
|
||||
@@ -188,16 +189,20 @@ class ToolsMenu(tk.Menu): # pylint:disable=too-many-ancestors
|
||||
|
||||
def update(self):
|
||||
""" Check for updates and clone repo """
|
||||
logger.debug("Updating Faceswap")
|
||||
logger.debug("Updating Faceswap...")
|
||||
self.root.config(cursor="watch")
|
||||
self.clear_console()
|
||||
encoding = locale.getpreferredencoding()
|
||||
logger.debug("Encoding: %s", encoding)
|
||||
success = False
|
||||
if self.check_for_updates(encoding):
|
||||
self.do_update(encoding)
|
||||
success = self.do_update(encoding)
|
||||
update_deps.main(logger=logger)
|
||||
if success:
|
||||
logger.info("Please restart Faceswap to complete the update.")
|
||||
self.root.config(cursor="")
|
||||
|
||||
def check_for_updates(self, encoding):
|
||||
@staticmethod
|
||||
def check_for_updates(encoding):
|
||||
""" Check whether an update is required """
|
||||
# Do the check
|
||||
logger.info("Checking for updates...")
|
||||
@@ -227,7 +232,6 @@ class ToolsMenu(tk.Menu): # pylint:disable=too-many-ancestors
|
||||
if "have diverged" in line.lower():
|
||||
msg = "Your branch has diverged from the remote repo. Not updating"
|
||||
break
|
||||
self.clear_console()
|
||||
if not update:
|
||||
logger.info(msg)
|
||||
logger.debug("Checked for update. Update required: %s", update)
|
||||
@@ -249,7 +253,8 @@ class ToolsMenu(tk.Menu): # pylint:disable=too-many-ancestors
|
||||
retcode = cmd.poll()
|
||||
logger.debug("'%s' returncode: %s", gitcmd, retcode)
|
||||
if retcode != 0:
|
||||
msg = "An error occurred during update. return code: {}".format(retcode)
|
||||
logger.info("An error occurred during update. return code: %s", retcode)
|
||||
retval = False
|
||||
else:
|
||||
msg = "Please restart Faceswap to complete the update."
|
||||
logger.info(msg)
|
||||
retval = True
|
||||
return retval
|
||||
|
||||
14
setup.py
14
setup.py
@@ -540,6 +540,7 @@ class Install():
|
||||
if self.env.enable_cuda and self.env.is_macos:
|
||||
self.env.required_packages.extend(self.env.macos_required_packages)
|
||||
for pkg in self.env.required_packages:
|
||||
pkg = self.check_os_requirements(pkg)
|
||||
key = pkg.split("==")[0]
|
||||
if key not in self.env.installed_packages:
|
||||
self.env.missing_packages.append(pkg)
|
||||
@@ -550,6 +551,19 @@ class Install():
|
||||
self.env.missing_packages.append(pkg)
|
||||
continue
|
||||
|
||||
@staticmethod
|
||||
def check_os_requirements(package):
|
||||
""" Check that the required package is required for this OS """
|
||||
if ";" not in package and "sys_platform" not in package:
|
||||
return package
|
||||
package = "".join(package.split())
|
||||
pkg, tags = package.split(";")
|
||||
tags = tags.split("==")
|
||||
sys_platform = tags[tags.index("sys_platform") + 1].replace('"', "").replace("'", "")
|
||||
if sys_platform == sys.platform:
|
||||
return pkg
|
||||
return None
|
||||
|
||||
def check_conda_missing_dep(self):
|
||||
""" Check for conda missing dependencies """
|
||||
if not self.env.is_conda:
|
||||
|
||||
192
update_deps.py
Normal file
192
update_deps.py
Normal file
@@ -0,0 +1,192 @@
|
||||
#!/usr/bin/env python3
|
||||
""" Installs any required third party libs for faceswap.py
|
||||
|
||||
Checks for installed Conda / Pip packages and updates accordingly
|
||||
"""
|
||||
|
||||
import locale
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import ctypes
|
||||
|
||||
from subprocess import CalledProcessError, run, PIPE, Popen
|
||||
|
||||
_LOGGER = None
|
||||
|
||||
|
||||
class Environment():
|
||||
""" Hold information about the running environment """
|
||||
def __init__(self):
|
||||
self.is_conda = "conda" in sys.version.lower()
|
||||
self.encoding = locale.getpreferredencoding()
|
||||
self.is_admin = self.get_admin_status()
|
||||
self.is_virtualenv = self.get_virtualenv
|
||||
required_packages = self.get_required_packages()
|
||||
self.installed_packages = self.get_installed_packages()
|
||||
self.get_installed_conda_packages()
|
||||
self.packages_to_install = self.get_packages_to_install(required_packages)
|
||||
|
||||
@staticmethod
|
||||
def get_admin_status():
|
||||
""" Check whether user is admin """
|
||||
try:
|
||||
retval = os.getuid() == 0
|
||||
except AttributeError:
|
||||
retval = ctypes.windll.shell32.IsUserAnAdmin() != 0
|
||||
return retval
|
||||
|
||||
def get_virtualenv(self):
|
||||
""" Check whether this is a virtual environment """
|
||||
if not self.is_conda:
|
||||
retval = (hasattr(sys, "real_prefix") or
|
||||
(hasattr(sys, "base_prefix") and sys.base_prefix != sys.prefix))
|
||||
else:
|
||||
prefix = os.path.dirname(sys.prefix)
|
||||
retval = (os.path.basename(prefix) == "envs")
|
||||
return retval
|
||||
|
||||
@staticmethod
|
||||
def get_required_packages():
|
||||
""" Load requirements list """
|
||||
packages = list()
|
||||
pypath = os.path.dirname(os.path.realpath(__file__))
|
||||
requirements_file = os.path.join(pypath, "requirements.txt")
|
||||
with open(requirements_file) as req:
|
||||
for package in req.readlines():
|
||||
package = package.strip()
|
||||
if package and (not package.startswith("#")):
|
||||
packages.append(package)
|
||||
return packages
|
||||
|
||||
def get_installed_packages(self):
|
||||
""" Get currently installed packages """
|
||||
installed_packages = dict()
|
||||
chk = Popen("\"{}\" -m pip freeze".format(sys.executable),
|
||||
shell=True, stdout=PIPE)
|
||||
installed = chk.communicate()[0].decode(self.encoding).splitlines()
|
||||
|
||||
for pkg in installed:
|
||||
if "==" not in pkg:
|
||||
continue
|
||||
item = pkg.split("==")
|
||||
installed_packages[item[0]] = item[1]
|
||||
return installed_packages
|
||||
|
||||
def get_installed_conda_packages(self):
|
||||
""" Get currently installed conda packages """
|
||||
if not self.is_conda:
|
||||
return
|
||||
chk = os.popen("conda list").read()
|
||||
installed = [re.sub(" +", " ", line.strip())
|
||||
for line in chk.splitlines() if not line.startswith("#")]
|
||||
for pkg in installed:
|
||||
item = pkg.split(" ")
|
||||
self.installed_packages[item[0]] = item[1]
|
||||
|
||||
def get_packages_to_install(self, required_packages):
|
||||
""" Get packages which need installing, upgrading or downgrading """
|
||||
to_install = list()
|
||||
for pkg in required_packages:
|
||||
pkg = self.check_os_requirement(pkg)
|
||||
if pkg is None:
|
||||
continue
|
||||
key = pkg.split("==")[0]
|
||||
if key not in self.installed_packages:
|
||||
to_install.append(pkg)
|
||||
else:
|
||||
if (len(pkg.split("==")) > 1 and
|
||||
pkg.split("==")[1] != self.installed_packages.get(key)):
|
||||
to_install.append(pkg)
|
||||
return to_install
|
||||
|
||||
@staticmethod
|
||||
def check_os_requirement(package):
|
||||
""" Check whether this package is required for this OS """
|
||||
if ";" not in package and "sys_platform" not in package:
|
||||
return package
|
||||
package = "".join(package.split())
|
||||
pkg, tags = package.split(";")
|
||||
tags = tags.split("==")
|
||||
sys_platform = tags[tags.index("sys_platform") + 1].replace('"', "").replace("'", "")
|
||||
if sys_platform == sys.platform:
|
||||
return pkg
|
||||
return None
|
||||
|
||||
|
||||
class Installer():
|
||||
""" Install packages through Conda or Pip """
|
||||
def __init__(self, environment):
|
||||
self.packages = environment.packages_to_install
|
||||
self.env = environment
|
||||
self.install()
|
||||
|
||||
def install(self):
|
||||
""" Install required pip packages """
|
||||
success = True
|
||||
for pkg in self.packages:
|
||||
output("Installing {}".format(pkg))
|
||||
if self.env.is_conda and self.conda_install(pkg):
|
||||
continue
|
||||
if not self.pip_install(pkg):
|
||||
success = False
|
||||
if not success:
|
||||
output("There were problems updating one or more dependencies.")
|
||||
else:
|
||||
output("Dependencies succesfully updated.")
|
||||
|
||||
@staticmethod
|
||||
def conda_install(package):
|
||||
""" Install a conda package """
|
||||
success = True
|
||||
condaexe = ["conda", "install", "-y", package]
|
||||
try:
|
||||
with open(os.devnull, "w") as devnull:
|
||||
run(condaexe, stdout=devnull, stderr=devnull, check=True)
|
||||
except CalledProcessError:
|
||||
output("{} not available in Conda. Installing with pip...".format(package))
|
||||
success = False
|
||||
return success
|
||||
|
||||
def pip_install(self, package):
|
||||
""" Install a pip package """
|
||||
success = True
|
||||
pipexe = [sys.executable, "-m", "pip"]
|
||||
# hide info/warning and fix cache hang
|
||||
pipexe.extend(["install", "-qq", "--no-cache-dir"])
|
||||
# install as user to solve perm restriction
|
||||
if not self.env.is_admin and not self.env.is_virtualenv:
|
||||
pipexe.append("--user")
|
||||
pipexe.append(package)
|
||||
try:
|
||||
run(pipexe, check=True)
|
||||
except CalledProcessError:
|
||||
output("Couldn't install {}. Please install this package manually".format(package))
|
||||
success = False
|
||||
return success
|
||||
|
||||
|
||||
def output(msg):
|
||||
""" Output to print or logger """
|
||||
if _LOGGER is not None:
|
||||
_LOGGER.info(msg)
|
||||
else:
|
||||
print(msg)
|
||||
|
||||
|
||||
def main(logger=None):
|
||||
""" Check for and update dependencies """
|
||||
if logger is not None:
|
||||
global _LOGGER # pylint:disable=global-statement
|
||||
_LOGGER = logger
|
||||
output("Updating Dependencies...")
|
||||
update = Environment()
|
||||
packages = update.packages_to_install
|
||||
if not packages:
|
||||
output("All Dependencies are up to date")
|
||||
else:
|
||||
Installer(update)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user