mirror of
https://github.com/deepfakes/faceswap
synced 2025-06-07 10:43:27 -04:00
setup.py: implement logging
This commit is contained in:
parent
dcb436c9df
commit
03f6cb4e7e
12 changed files with 732 additions and 403 deletions
|
@ -385,7 +385,7 @@ setup_faceswap() {
|
||||||
# Run faceswap setup script
|
# Run faceswap setup script
|
||||||
info "Setting up Faceswap..."
|
info "Setting up Faceswap..."
|
||||||
if [ $VERSION != "cpu" ] ; then args="--$VERSION" ; else args="" ; fi
|
if [ $VERSION != "cpu" ] ; then args="--$VERSION" ; else args="" ; fi
|
||||||
python "$DIR_FACESWAP/setup.py" --installer $args
|
python -u "$DIR_FACESWAP/setup.py" --installer $args
|
||||||
}
|
}
|
||||||
|
|
||||||
create_gui_launcher () {
|
create_gui_launcher () {
|
||||||
|
|
|
@ -448,7 +448,7 @@ Function SetupFaceSwap
|
||||||
StrCpy $0 "$0 --$setupType"
|
StrCpy $0 "$0 --$setupType"
|
||||||
${EndIf}
|
${EndIf}
|
||||||
SetDetailsPrint listonly
|
SetDetailsPrint listonly
|
||||||
ExecDos::exec /NOUNLOAD /ASYNC /DETAILED "$\"$dirConda\scripts\activate.bat$\" && conda activate $\"$envName$\" && python $\"$INSTDIR\setup.py$\" $0 && conda deactivate"
|
ExecDos::exec /NOUNLOAD /ASYNC /DETAILED "$\"$dirConda\scripts\activate.bat$\" && conda activate $\"$envName$\" && python -u $\"$INSTDIR\setup.py$\" $0 && conda deactivate"
|
||||||
pop $0
|
pop $0
|
||||||
ExecDos::wait $0
|
ExecDos::wait $0
|
||||||
pop $0
|
pop $0
|
||||||
|
|
|
@ -8,3 +8,5 @@ faceswap
|
||||||
plugins/plugins
|
plugins/plugins
|
||||||
scripts
|
scripts
|
||||||
tools/tools
|
tools/tools
|
||||||
|
setup
|
||||||
|
update_deps
|
||||||
|
|
8
docs/full/setup.rst
Normal file
8
docs/full/setup.rst
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
************
|
||||||
|
setup module
|
||||||
|
************
|
||||||
|
|
||||||
|
.. automodule:: setup
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
8
docs/full/update_deps.rst
Normal file
8
docs/full/update_deps.rst
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
******************
|
||||||
|
update_deps module
|
||||||
|
******************
|
||||||
|
|
||||||
|
.. automodule:: update_deps
|
||||||
|
:members:
|
||||||
|
:undoc-members:
|
||||||
|
:show-inheritance:
|
|
@ -238,6 +238,7 @@ class _SysOutRouter():
|
||||||
self._console = console
|
self._console = console
|
||||||
self._out_type = out_type
|
self._out_type = out_type
|
||||||
self._recolor = re.compile(r".+?(\s\d+:\d+:\d+\s)(?P<lvl>[A-Z]+)\s")
|
self._recolor = re.compile(r".+?(\s\d+:\d+:\d+\s)(?P<lvl>[A-Z]+)\s")
|
||||||
|
self._ansi_escape = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])")
|
||||||
logger.debug("Initialized %s", self.__class__.__name__)
|
logger.debug("Initialized %s", self.__class__.__name__)
|
||||||
|
|
||||||
def _get_tag(self, string):
|
def _get_tag(self, string):
|
||||||
|
@ -254,6 +255,7 @@ class _SysOutRouter():
|
||||||
|
|
||||||
def write(self, string):
|
def write(self, string):
|
||||||
""" Capture stdout/stderr """
|
""" Capture stdout/stderr """
|
||||||
|
string = self._ansi_escape.sub("", string)
|
||||||
self._console.insert(tk.END, string, self._get_tag(string))
|
self._console.insert(tk.END, string, self._get_tag(string))
|
||||||
self._console.see(tk.END)
|
self._console.see(tk.END)
|
||||||
|
|
||||||
|
@ -315,9 +317,8 @@ class _WidgetRedirector:
|
||||||
tk_.createcommand(wgt, self.dispatch)
|
tk_.createcommand(wgt, self.dispatch)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "%s(%s<%s>)" % (self.__class__.__name__,
|
return (f"{self.__class__.__name__}({self.widget.__class__.__name__}"
|
||||||
self.widget.__class__.__name__,
|
f"<{self.widget._w}>)") # pylint:disable=protected-access
|
||||||
self.widget._w) # pylint:disable=protected-access
|
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
"de-register operations and revert redirection created by .__init__."
|
"de-register operations and revert redirection created by .__init__."
|
||||||
|
@ -409,8 +410,7 @@ class _OriginalCommand:
|
||||||
self.orig_and_operation = (redirect.orig, operation)
|
self.orig_and_operation = (redirect.orig, operation)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "%s(%r, %r)" % (self.__class__.__name__,
|
return f"{self.__class__.__name__}({self.redirect}, {self.operation})"
|
||||||
self.redirect, self.operation)
|
|
||||||
|
|
||||||
def __call__(self, *args):
|
def __call__(self, *args):
|
||||||
return self.tk_call(self.orig_and_operation + args)
|
return self.tk_call(self.orig_and_operation + args)
|
||||||
|
@ -619,12 +619,8 @@ class Tooltip: # pylint:disable=too-few-public-methods
|
||||||
x_1, y_1 = mouse_x + tip_delta[0], mouse_y + tip_delta[1]
|
x_1, y_1 = mouse_x + tip_delta[0], mouse_y + tip_delta[1]
|
||||||
x_2, y_2 = x_1 + width, y_1 + height
|
x_2, y_2 = x_1 + width, y_1 + height
|
||||||
|
|
||||||
x_delta = x_2 - s_width
|
x_delta = max(x_2 - s_width, 0)
|
||||||
if x_delta < 0:
|
y_delta = max(y_2 - s_height, 0)
|
||||||
x_delta = 0
|
|
||||||
y_delta = y_2 - s_height
|
|
||||||
if y_delta < 0:
|
|
||||||
y_delta = 0
|
|
||||||
|
|
||||||
offscreen = (x_delta, y_delta) != (0, 0)
|
offscreen = (x_delta, y_delta) != (0, 0)
|
||||||
|
|
||||||
|
@ -670,7 +666,7 @@ class Tooltip: # pylint:disable=too-few-public-methods
|
||||||
|
|
||||||
text = self._text
|
text = self._text
|
||||||
if self._text_variable and self._text_variable.get():
|
if self._text_variable and self._text_variable.get():
|
||||||
text += "\n\nCurrent value: '{}'".format(self._text_variable.get())
|
text += f"\n\nCurrent value: '{self._text_variable.get()}'"
|
||||||
label = tk.Label(win,
|
label = tk.Label(win,
|
||||||
text=text,
|
text=text,
|
||||||
justify=tk.LEFT,
|
justify=tk.LEFT,
|
||||||
|
@ -687,7 +683,7 @@ class Tooltip: # pylint:disable=too-few-public-methods
|
||||||
|
|
||||||
xpos, ypos = tip_pos_calculator(widget, label)
|
xpos, ypos = tip_pos_calculator(widget, label)
|
||||||
|
|
||||||
self._topwidget.wm_geometry("+%d+%d" % (xpos, ypos))
|
self._topwidget.wm_geometry(f"+{xpos}+{ypos}")
|
||||||
|
|
||||||
def _hide(self):
|
def _hide(self):
|
||||||
""" Hide the tooltip """
|
""" Hide the tooltip """
|
||||||
|
@ -819,7 +815,7 @@ class PopupProgress(tk.Toplevel):
|
||||||
center = np.array((
|
center = np.array((
|
||||||
(self.master.winfo_width() // 2) - (self.winfo_width() // 2),
|
(self.master.winfo_width() // 2) - (self.winfo_width() // 2),
|
||||||
(self.master.winfo_height() // 2) - (self.winfo_height() // 2))) + offset
|
(self.master.winfo_height() // 2) - (self.winfo_height() // 2))) + offset
|
||||||
self.wm_geometry("+{}+{}".format(*center))
|
self.wm_geometry(f"+{center[0]}+{center[1]}")
|
||||||
get_config().set_cursor_busy()
|
get_config().set_cursor_busy()
|
||||||
self.grab_set()
|
self.grab_set()
|
||||||
|
|
||||||
|
|
|
@ -166,10 +166,10 @@ class FileMenu(tk.Menu): # pylint:disable=too-many-ancestors
|
||||||
kwargs = dict(filename=filename)
|
kwargs = dict(filename=filename)
|
||||||
else:
|
else:
|
||||||
load_func = self._config.tasks.load
|
load_func = self._config.tasks.load
|
||||||
lbl = "{} Task".format(command)
|
lbl = f"{command} Task"
|
||||||
kwargs = dict(filename=filename, current_tab=False)
|
kwargs = dict(filename=filename, current_tab=False)
|
||||||
self.recent_menu.add_command(
|
self.recent_menu.add_command(
|
||||||
label="{} ({})".format(filename, lbl.title()),
|
label=f"{filename} ({lbl.title()})",
|
||||||
command=lambda kw=kwargs, fn=load_func: fn(**kw))
|
command=lambda kw=kwargs, fn=load_func: fn(**kw))
|
||||||
if removed_files:
|
if removed_files:
|
||||||
for recent_item in removed_files:
|
for recent_item in removed_files:
|
||||||
|
@ -188,7 +188,7 @@ class FileMenu(tk.Menu): # pylint:disable=too-many-ancestors
|
||||||
def clear_recent_files(serializer, menu_file):
|
def clear_recent_files(serializer, menu_file):
|
||||||
""" Creates or clears recent file list """
|
""" Creates or clears recent file list """
|
||||||
logger.debug("clearing recent files list: '%s'", menu_file)
|
logger.debug("clearing recent files list: '%s'", menu_file)
|
||||||
serializer.save(menu_file, list())
|
serializer.save(menu_file, [])
|
||||||
|
|
||||||
def refresh_recent_menu(self):
|
def refresh_recent_menu(self):
|
||||||
""" Refresh recent menu on save/load of files """
|
""" Refresh recent menu on save/load of files """
|
||||||
|
@ -263,9 +263,9 @@ class HelpMenu(tk.Menu): # pylint:disable=too-many-ancestors
|
||||||
error then `None` is returned
|
error then `None` is returned
|
||||||
"""
|
"""
|
||||||
gitcmd = "git branch -a"
|
gitcmd = "git branch -a"
|
||||||
cmd = Popen(gitcmd, shell=True, stdout=PIPE, stderr=STDOUT, cwd=_WORKING_DIR)
|
with Popen(gitcmd, shell=True, stdout=PIPE, stderr=STDOUT, cwd=_WORKING_DIR) as cmd:
|
||||||
stdout, _ = cmd.communicate()
|
stdout, _ = cmd.communicate()
|
||||||
retcode = cmd.poll()
|
retcode = cmd.poll()
|
||||||
if retcode != 0:
|
if retcode != 0:
|
||||||
logger.debug("Unable to list git branches. return code: %s, message: %s",
|
logger.debug("Unable to list git branches. return code: %s, message: %s",
|
||||||
retcode, stdout.decode().strip().replace("\n", " - "))
|
retcode, stdout.decode().strip().replace("\n", " - "))
|
||||||
|
@ -315,10 +315,10 @@ class HelpMenu(tk.Menu): # pylint:disable=too-many-ancestors
|
||||||
The branch to switch to
|
The branch to switch to
|
||||||
"""
|
"""
|
||||||
logger.info("Switching branch to '%s'...", branch)
|
logger.info("Switching branch to '%s'...", branch)
|
||||||
gitcmd = "git checkout {}".format(branch)
|
gitcmd = f"git checkout {branch}"
|
||||||
cmd = Popen(gitcmd, shell=True, stdout=PIPE, stderr=STDOUT, cwd=_WORKING_DIR)
|
with Popen(gitcmd, shell=True, stdout=PIPE, stderr=STDOUT, cwd=_WORKING_DIR) as cmd:
|
||||||
stdout, _ = cmd.communicate()
|
stdout, _ = cmd.communicate()
|
||||||
retcode = cmd.poll()
|
retcode = cmd.poll()
|
||||||
if retcode != 0:
|
if retcode != 0:
|
||||||
logger.error("Unable to switch branch. return code: %s, message: %s",
|
logger.error("Unable to switch branch. return code: %s, message: %s",
|
||||||
retcode, stdout.decode().strip().replace("\n", " - "))
|
retcode, stdout.decode().strip().replace("\n", " - "))
|
||||||
|
@ -358,7 +358,7 @@ class HelpMenu(tk.Menu): # pylint:disable=too-many-ancestors
|
||||||
from lib.sysinfo import sysinfo # pylint:disable=import-outside-toplevel
|
from lib.sysinfo import sysinfo # pylint:disable=import-outside-toplevel
|
||||||
info = sysinfo
|
info = sysinfo
|
||||||
except Exception as err: # pylint:disable=broad-except
|
except Exception as err: # pylint:disable=broad-except
|
||||||
info = "Error obtaining system info: {}".format(str(err))
|
info = f"Error obtaining system info: {str(err)}"
|
||||||
self.clear_console()
|
self.clear_console()
|
||||||
logger.debug("Obtained system information: %s", info)
|
logger.debug("Obtained system information: %s", info)
|
||||||
print(info)
|
print(info)
|
||||||
|
@ -382,7 +382,7 @@ class HelpMenu(tk.Menu): # pylint:disable=too-many-ancestors
|
||||||
success = False
|
success = False
|
||||||
if self.check_for_updates(encoding):
|
if self.check_for_updates(encoding):
|
||||||
success = self.do_update(encoding)
|
success = self.do_update(encoding)
|
||||||
update_deps.main(logger=logger)
|
update_deps.main(is_gui=True)
|
||||||
if success:
|
if success:
|
||||||
logger.info("Please restart Faceswap to complete the update.")
|
logger.info("Please restart Faceswap to complete the update.")
|
||||||
self.root.config(cursor="")
|
self.root.config(cursor="")
|
||||||
|
@ -395,9 +395,9 @@ class HelpMenu(tk.Menu): # pylint:disable=too-many-ancestors
|
||||||
update = False
|
update = False
|
||||||
msg = ""
|
msg = ""
|
||||||
gitcmd = "git remote update && git status -uno"
|
gitcmd = "git remote update && git status -uno"
|
||||||
cmd = Popen(gitcmd, shell=True, stdout=PIPE, stderr=STDOUT, cwd=_WORKING_DIR)
|
with Popen(gitcmd, shell=True, stdout=PIPE, stderr=STDOUT, cwd=_WORKING_DIR) as cmd:
|
||||||
stdout, _ = cmd.communicate()
|
stdout, _ = cmd.communicate()
|
||||||
retcode = cmd.poll()
|
retcode = cmd.poll()
|
||||||
if retcode != 0:
|
if retcode != 0:
|
||||||
msg = ("Git is not installed or you are not running a cloned repo. "
|
msg = ("Git is not installed or you are not running a cloned repo. "
|
||||||
"Unable to check for updates")
|
"Unable to check for updates")
|
||||||
|
@ -427,15 +427,20 @@ class HelpMenu(tk.Menu): # pylint:disable=too-many-ancestors
|
||||||
""" Update Faceswap """
|
""" Update Faceswap """
|
||||||
logger.info("A new version is available. Updating...")
|
logger.info("A new version is available. Updating...")
|
||||||
gitcmd = "git pull"
|
gitcmd = "git pull"
|
||||||
cmd = Popen(gitcmd, shell=True, stdout=PIPE, stderr=STDOUT, bufsize=1, cwd=_WORKING_DIR)
|
with Popen(gitcmd,
|
||||||
while True:
|
shell=True,
|
||||||
output = cmd.stdout.readline().decode(encoding)
|
stdout=PIPE,
|
||||||
if output == "" and cmd.poll() is not None:
|
stderr=STDOUT,
|
||||||
break
|
bufsize=1,
|
||||||
if output:
|
cwd=_WORKING_DIR) as cmd:
|
||||||
logger.debug("'%s' output: '%s'", gitcmd, output.strip())
|
while True:
|
||||||
print(output.strip())
|
output = cmd.stdout.readline().decode(encoding)
|
||||||
retcode = cmd.poll()
|
if output == "" and cmd.poll() is not None:
|
||||||
|
break
|
||||||
|
if output:
|
||||||
|
logger.debug("'%s' output: '%s'", gitcmd, output.strip())
|
||||||
|
print(output.strip())
|
||||||
|
retcode = cmd.poll()
|
||||||
logger.debug("'%s' returncode: %s", gitcmd, retcode)
|
logger.debug("'%s' returncode: %s", gitcmd, retcode)
|
||||||
if retcode != 0:
|
if retcode != 0:
|
||||||
logger.info("An error occurred during update. return code: %s", retcode)
|
logger.info("An error occurred during update. return code: %s", retcode)
|
||||||
|
@ -482,7 +487,7 @@ class TaskBar(ttk.Frame): # pylint: disable=too-many-ancestors
|
||||||
frame.pack(side=tk.LEFT, anchor=tk.W, expand=False, padx=2)
|
frame.pack(side=tk.LEFT, anchor=tk.W, expand=False, padx=2)
|
||||||
|
|
||||||
for loadtype in ("load", "save", "save_as", "clear", "reload"):
|
for loadtype in ("load", "save", "save_as", "clear", "reload"):
|
||||||
btntype = "{}2".format(loadtype)
|
btntype = f"{loadtype}2"
|
||||||
logger.debug("Adding button: '%s'", btntype)
|
logger.debug("Adding button: '%s'", btntype)
|
||||||
|
|
||||||
loader, kwargs = self._loader_and_kwargs(loadtype)
|
loader, kwargs = self._loader_and_kwargs(loadtype)
|
||||||
|
@ -507,7 +512,7 @@ class TaskBar(ttk.Frame): # pylint: disable=too-many-ancestors
|
||||||
kwargs = dict(save_as=True)
|
kwargs = dict(save_as=True)
|
||||||
else:
|
else:
|
||||||
loader = btntype
|
loader = btntype
|
||||||
kwargs = dict()
|
kwargs = {}
|
||||||
logger.debug("btntype: %s, loader: %s, kwargs: %s", btntype, loader, kwargs)
|
logger.debug("btntype: %s, loader: %s, kwargs: %s", btntype, loader, kwargs)
|
||||||
return loader, kwargs
|
return loader, kwargs
|
||||||
|
|
||||||
|
@ -516,7 +521,7 @@ class TaskBar(ttk.Frame): # pylint: disable=too-many-ancestors
|
||||||
frame = ttk.Frame(self._btn_frame)
|
frame = ttk.Frame(self._btn_frame)
|
||||||
frame.pack(side=tk.LEFT, anchor=tk.W, expand=False, padx=2)
|
frame.pack(side=tk.LEFT, anchor=tk.W, expand=False, padx=2)
|
||||||
for name in ("extract", "train", "convert"):
|
for name in ("extract", "train", "convert"):
|
||||||
btntype = "settings_{}".format(name)
|
btntype = f"settings_{name}"
|
||||||
btntype = btntype if btntype in get_images().icons else "settings"
|
btntype = btntype if btntype in get_images().icons else "settings"
|
||||||
logger.debug("Adding button: '%s'", btntype)
|
logger.debug("Adding button: '%s'", btntype)
|
||||||
btn = ttk.Button(
|
btn = ttk.Button(
|
||||||
|
|
201
lib/logger.py
201
lib/logger.py
|
@ -4,16 +4,19 @@ import collections
|
||||||
import logging
|
import logging
|
||||||
from logging.handlers import RotatingFileHandler
|
from logging.handlers import RotatingFileHandler
|
||||||
import os
|
import os
|
||||||
|
import platform
|
||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from tqdm import tqdm
|
from typing import Union
|
||||||
|
|
||||||
|
|
||||||
class FaceswapLogger(logging.Logger):
|
class FaceswapLogger(logging.Logger):
|
||||||
""" A standard :class:`logging.logger` with additional "verbose" and "trace" levels added. """
|
""" A standard :class:`logging.logger` with additional "verbose" and "trace" levels added. """
|
||||||
def __init__(self, name):
|
def __init__(self, name: str) -> None:
|
||||||
for new_level in (("VERBOSE", 15), ("TRACE", 5)):
|
for new_level in (("VERBOSE", 15), ("TRACE", 5)):
|
||||||
level_name, level_num = new_level
|
level_name, level_num = new_level
|
||||||
if hasattr(logging, level_name):
|
if hasattr(logging, level_name):
|
||||||
|
@ -22,7 +25,7 @@ class FaceswapLogger(logging.Logger):
|
||||||
setattr(logging, level_name, level_num)
|
setattr(logging, level_name, level_num)
|
||||||
super().__init__(name)
|
super().__init__(name)
|
||||||
|
|
||||||
def verbose(self, msg, *args, **kwargs):
|
def verbose(self, msg: str, *args, **kwargs) -> None:
|
||||||
# pylint:disable=wrong-spelling-in-docstring
|
# pylint:disable=wrong-spelling-in-docstring
|
||||||
""" Create a log message at severity level 15.
|
""" Create a log message at severity level 15.
|
||||||
|
|
||||||
|
@ -38,7 +41,7 @@ class FaceswapLogger(logging.Logger):
|
||||||
if self.isEnabledFor(15):
|
if self.isEnabledFor(15):
|
||||||
self._log(15, msg, args, **kwargs)
|
self._log(15, msg, args, **kwargs)
|
||||||
|
|
||||||
def trace(self, msg, *args, **kwargs):
|
def trace(self, msg: str, *args, **kwargs) -> None:
|
||||||
# pylint:disable=wrong-spelling-in-docstring
|
# pylint:disable=wrong-spelling-in-docstring
|
||||||
""" Create a log message at severity level 5.
|
""" Create a log message at severity level 5.
|
||||||
|
|
||||||
|
@ -55,6 +58,102 @@ class FaceswapLogger(logging.Logger):
|
||||||
self._log(5, msg, args, **kwargs)
|
self._log(5, msg, args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class ColoredFormatter(logging.Formatter):
|
||||||
|
""" Overrides the stand :class:`logging.Formatter` to enable colored labels for message level
|
||||||
|
labels on supported platforms
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
fmt: str
|
||||||
|
The format string for the message as a whole
|
||||||
|
pad_newlines: bool, Optional
|
||||||
|
If ``True`` new lines will be padded to appear in line with the log message, if ``False``
|
||||||
|
they will be left aligned
|
||||||
|
|
||||||
|
kwargs: dict
|
||||||
|
Standard :class:`logging.Formatter` keyword arguments
|
||||||
|
"""
|
||||||
|
def __init__(self, fmt: str, pad_newlines: bool = False, **kwargs) -> None:
|
||||||
|
super().__init__(fmt, **kwargs)
|
||||||
|
self._use_color = platform.system().lower() in ("linux", "darwin")
|
||||||
|
self._level_colors = dict(CRITICAL="\033[31m", # red
|
||||||
|
ERROR="\033[31m", # red
|
||||||
|
WARNING="\033[33m", # yellow
|
||||||
|
INFO="\033[32m", # green
|
||||||
|
VERBOSE="\033[34m") # blue
|
||||||
|
self._default_color = "\033[0m"
|
||||||
|
self._newline_padding = self._get_newline_padding(pad_newlines, fmt)
|
||||||
|
|
||||||
|
def _get_newline_padding(self, pad_newlines: bool, fmt: str) -> int:
|
||||||
|
""" Parses the format string to obtain padding for newlines if requested
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
fmt: str
|
||||||
|
The format string for the message as a whole
|
||||||
|
pad_newlines: bool, Optional
|
||||||
|
If ``True`` new lines will be padded to appear in line with the log message, if
|
||||||
|
``False`` they will be left aligned
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
int
|
||||||
|
The amount of padding to apply to the front of newlines
|
||||||
|
"""
|
||||||
|
if not pad_newlines:
|
||||||
|
return 0
|
||||||
|
msg_idx = fmt.find("%(message)") + 1
|
||||||
|
filtered = fmt[:msg_idx - 1]
|
||||||
|
spaces = filtered.count(" ")
|
||||||
|
pads = [int(pad.replace("s", "")) for pad in re.findall(r"\ds", filtered)]
|
||||||
|
if "asctime" in filtered:
|
||||||
|
pads.append(self._get_sample_time_string())
|
||||||
|
return sum(pads) + spaces
|
||||||
|
|
||||||
|
def _get_sample_time_string(self) -> int:
|
||||||
|
""" Obtain a sample time string and calculate correct padding.
|
||||||
|
|
||||||
|
This may be inaccurate wheb ticking over an integer from single to double digits, but that
|
||||||
|
shouldn't be a huge issue.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
int
|
||||||
|
The length of the formatted date-time string
|
||||||
|
"""
|
||||||
|
sample_time = time.time()
|
||||||
|
date_format = self.datefmt if self.datefmt else self.default_time_format
|
||||||
|
datestring = time.strftime(date_format, logging.Formatter.converter(sample_time))
|
||||||
|
if not self.datefmt and self.default_msec_format:
|
||||||
|
msecs = (sample_time - int(sample_time)) * 1000
|
||||||
|
datestring = self.default_msec_format % (datestring, msecs)
|
||||||
|
return len(datestring)
|
||||||
|
|
||||||
|
def format(self, record: logging.LogRecord) -> str:
|
||||||
|
""" Color the log message level if supported otherwise return the standard log message.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
record: :class:`logging.LogRecord`
|
||||||
|
The incoming log record to be formatted for entry into the logger.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
str
|
||||||
|
The formatted log message
|
||||||
|
"""
|
||||||
|
formatted = super().format(record)
|
||||||
|
levelname = record.levelname
|
||||||
|
if self._use_color and levelname in self._level_colors:
|
||||||
|
formatted = re.sub(levelname,
|
||||||
|
f"{self._level_colors[levelname]}{levelname}{self._default_color}",
|
||||||
|
formatted,
|
||||||
|
1)
|
||||||
|
if self._newline_padding:
|
||||||
|
formatted = formatted.replace("\n", f"\n{' ' * self._newline_padding}")
|
||||||
|
return formatted
|
||||||
|
|
||||||
|
|
||||||
class FaceswapFormatter(logging.Formatter):
|
class FaceswapFormatter(logging.Formatter):
|
||||||
""" Overrides the standard :class:`logging.Formatter`.
|
""" Overrides the standard :class:`logging.Formatter`.
|
||||||
|
|
||||||
|
@ -63,7 +162,7 @@ class FaceswapFormatter(logging.Formatter):
|
||||||
Rewrites some upstream warning messages to debug level to avoid spamming the console.
|
Rewrites some upstream warning messages to debug level to avoid spamming the console.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def format(self, record):
|
def format(self, record: logging.LogRecord) -> str:
|
||||||
""" Strip new lines from log records and rewrite certain warning messages to debug level.
|
""" Strip new lines from log records and rewrite certain warning messages to debug level.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
|
@ -102,7 +201,7 @@ class FaceswapFormatter(logging.Formatter):
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _rewrite_warnings(cls, record):
|
def _rewrite_warnings(cls, record: logging.LogRecord) -> logging.LogRecord:
|
||||||
""" Change certain warning messages from WARNING to DEBUG to avoid passing non-important
|
""" Change certain warning messages from WARNING to DEBUG to avoid passing non-important
|
||||||
information to output.
|
information to output.
|
||||||
|
|
||||||
|
@ -133,7 +232,7 @@ class FaceswapFormatter(logging.Formatter):
|
||||||
return record
|
return record
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _lower_external(cls, record):
|
def _lower_external(cls, record: logging.LogRecord) -> logging.LogRecord:
|
||||||
""" Some external libs log at a higher level than we would really like, so lower their
|
""" Some external libs log at a higher level than we would really like, so lower their
|
||||||
log level.
|
log level.
|
||||||
|
|
||||||
|
@ -162,7 +261,7 @@ class RollingBuffer(collections.deque):
|
||||||
"""File-like that keeps a certain number of lines of text in memory for writing out to the
|
"""File-like that keeps a certain number of lines of text in memory for writing out to the
|
||||||
crash log. """
|
crash log. """
|
||||||
|
|
||||||
def write(self, buffer):
|
def write(self, buffer: str) -> None:
|
||||||
""" Splits lines from the incoming buffer and writes them out to the rolling buffer.
|
""" Splits lines from the incoming buffer and writes them out to the rolling buffer.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
|
@ -178,7 +277,7 @@ class TqdmHandler(logging.StreamHandler):
|
||||||
""" Overrides :class:`logging.StreamHandler` to use :func:`tqdm.tqdm.write` rather than writing
|
""" Overrides :class:`logging.StreamHandler` to use :func:`tqdm.tqdm.write` rather than writing
|
||||||
to :func:`sys.stderr` so that log messages do not mess up tqdm progress bars. """
|
to :func:`sys.stderr` so that log messages do not mess up tqdm progress bars. """
|
||||||
|
|
||||||
def emit(self, record):
|
def emit(self, record: logging.LogRecord) -> None:
|
||||||
""" Format the incoming message and pass to :func:`tqdm.tqdm.write`.
|
""" Format the incoming message and pass to :func:`tqdm.tqdm.write`.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
|
@ -186,11 +285,13 @@ class TqdmHandler(logging.StreamHandler):
|
||||||
record : :class:`logging.LogRecord`
|
record : :class:`logging.LogRecord`
|
||||||
The incoming log record to be formatted for entry into the logger.
|
The incoming log record to be formatted for entry into the logger.
|
||||||
"""
|
"""
|
||||||
|
# tqdm is imported here as it won't be installed when setup.py is running
|
||||||
|
from tqdm import tqdm # pylint:disable=import-outside-toplevel
|
||||||
msg = self.format(record)
|
msg = self.format(record)
|
||||||
tqdm.write(msg)
|
tqdm.write(msg)
|
||||||
|
|
||||||
|
|
||||||
def _set_root_logger(loglevel=logging.INFO):
|
def _set_root_logger(loglevel: int = logging.INFO) -> logging.Logger:
|
||||||
""" Setup the root logger.
|
""" Setup the root logger.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
|
@ -208,7 +309,7 @@ def _set_root_logger(loglevel=logging.INFO):
|
||||||
return rootlogger
|
return rootlogger
|
||||||
|
|
||||||
|
|
||||||
def log_setup(loglevel, log_file, command, is_gui=False):
|
def log_setup(loglevel, log_file: str, command: str, is_gui: bool = False) -> None:
|
||||||
""" Set up logging for Faceswap.
|
""" Set up logging for Faceswap.
|
||||||
|
|
||||||
Sets up the root logger, the formatting for the crash logger and the file logger, and sets up
|
Sets up the root logger, the formatting for the crash logger and the file logger, and sets up
|
||||||
|
@ -230,19 +331,32 @@ def log_setup(loglevel, log_file, command, is_gui=False):
|
||||||
numeric_loglevel = get_loglevel(loglevel)
|
numeric_loglevel = get_loglevel(loglevel)
|
||||||
root_loglevel = min(logging.DEBUG, numeric_loglevel)
|
root_loglevel = min(logging.DEBUG, numeric_loglevel)
|
||||||
rootlogger = _set_root_logger(loglevel=root_loglevel)
|
rootlogger = _set_root_logger(loglevel=root_loglevel)
|
||||||
log_format = FaceswapFormatter("%(asctime)s %(processName)-15s %(threadName)-30s "
|
|
||||||
"%(module)-15s %(funcName)-30s %(levelname)-8s %(message)s",
|
if command == "setup":
|
||||||
datefmt="%m/%d/%Y %H:%M:%S")
|
log_format = FaceswapFormatter("%(asctime)s %(module)-16s %(funcName)-30s %(levelname)-8s "
|
||||||
f_handler = _file_handler(numeric_loglevel, log_file, log_format, command)
|
"%(message)s", datefmt="%m/%d/%Y %H:%M:%S")
|
||||||
s_handler = _stream_handler(numeric_loglevel, is_gui)
|
s_handler = _stream_setup_handler(numeric_loglevel)
|
||||||
c_handler = _crash_handler(log_format)
|
f_handler = _file_handler(root_loglevel, log_file, log_format, command)
|
||||||
|
else:
|
||||||
|
log_format = FaceswapFormatter("%(asctime)s %(processName)-15s %(threadName)-30s "
|
||||||
|
"%(module)-15s %(funcName)-30s %(levelname)-8s %(message)s",
|
||||||
|
datefmt="%m/%d/%Y %H:%M:%S")
|
||||||
|
s_handler = _stream_handler(numeric_loglevel, is_gui)
|
||||||
|
f_handler = _file_handler(numeric_loglevel, log_file, log_format, command)
|
||||||
|
|
||||||
rootlogger.addHandler(f_handler)
|
rootlogger.addHandler(f_handler)
|
||||||
rootlogger.addHandler(s_handler)
|
rootlogger.addHandler(s_handler)
|
||||||
rootlogger.addHandler(c_handler)
|
|
||||||
logging.info("Log level set to: %s", loglevel.upper())
|
if command != "setup":
|
||||||
|
c_handler = _crash_handler(log_format)
|
||||||
|
rootlogger.addHandler(c_handler)
|
||||||
|
logging.info("Log level set to: %s", loglevel.upper())
|
||||||
|
|
||||||
|
|
||||||
def _file_handler(loglevel, log_file, log_format, command):
|
def _file_handler(loglevel,
|
||||||
|
log_file: str,
|
||||||
|
log_format: FaceswapFormatter,
|
||||||
|
command: str) -> RotatingFileHandler:
|
||||||
""" Add a rotating file handler for the current Faceswap session. 1 backup is always kept.
|
""" Add a rotating file handler for the current Faceswap session. 1 backup is always kept.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
|
@ -270,21 +384,21 @@ def _file_handler(loglevel, log_file, log_format, command):
|
||||||
filename += "_gui.log" if command == "gui" else ".log"
|
filename += "_gui.log" if command == "gui" else ".log"
|
||||||
|
|
||||||
should_rotate = os.path.isfile(filename)
|
should_rotate = os.path.isfile(filename)
|
||||||
log_file = RotatingFileHandler(filename, backupCount=1, encoding="utf-8")
|
handler = RotatingFileHandler(filename, backupCount=1, encoding="utf-8")
|
||||||
if should_rotate:
|
if should_rotate:
|
||||||
log_file.doRollover()
|
handler.doRollover()
|
||||||
log_file.setFormatter(log_format)
|
handler.setFormatter(log_format)
|
||||||
log_file.setLevel(loglevel)
|
handler.setLevel(loglevel)
|
||||||
return log_file
|
return handler
|
||||||
|
|
||||||
|
|
||||||
def _stream_handler(loglevel, is_gui):
|
def _stream_handler(loglevel: int, is_gui: bool) -> Union[logging.StreamHandler, TqdmHandler]:
|
||||||
""" Add a stream handler for the current Faceswap session. The stream handler will only ever
|
""" Add a stream handler for the current Faceswap session. The stream handler will only ever
|
||||||
output at a maximum of VERBOSE level to avoid spamming the console.
|
output at a maximum of VERBOSE level to avoid spamming the console.
|
||||||
|
|
||||||
Parameters
|
Parameters
|
||||||
----------
|
----------
|
||||||
loglevel: str
|
loglevel: int
|
||||||
The requested log level that messages should be logged at.
|
The requested log level that messages should be logged at.
|
||||||
is_gui: bool, optional
|
is_gui: bool, optional
|
||||||
Whether Faceswap is running in the GUI or not. Dictates where the stream handler should
|
Whether Faceswap is running in the GUI or not. Dictates where the stream handler should
|
||||||
|
@ -311,7 +425,30 @@ def _stream_handler(loglevel, is_gui):
|
||||||
return log_console
|
return log_console
|
||||||
|
|
||||||
|
|
||||||
def _crash_handler(log_format):
|
def _stream_setup_handler(loglevel: int) -> logging.StreamHandler:
|
||||||
|
""" Add a stream handler for faceswap's setup.py script
|
||||||
|
This stream handler outputs a limited set of easy to use information using colored labels
|
||||||
|
if available. It will only ever output at a minimum of INFO level
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
loglevel: int
|
||||||
|
The requested log level that messages should be logged at.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
:class:`logging.StreamHandler`
|
||||||
|
The stream handler to use
|
||||||
|
"""
|
||||||
|
loglevel = max(loglevel, 15)
|
||||||
|
log_format = ColoredFormatter("%(levelname)-8s %(message)s", pad_newlines=True)
|
||||||
|
handler = logging.StreamHandler(sys.stdout)
|
||||||
|
handler.setFormatter(log_format)
|
||||||
|
handler.setLevel(loglevel)
|
||||||
|
return handler
|
||||||
|
|
||||||
|
|
||||||
|
def _crash_handler(log_format: FaceswapFormatter) -> logging.StreamHandler:
|
||||||
""" Add a handler that stores the last 100 debug lines to :attr:'_DEBUG_BUFFER' for use in
|
""" Add a handler that stores the last 100 debug lines to :attr:'_DEBUG_BUFFER' for use in
|
||||||
crash reports.
|
crash reports.
|
||||||
|
|
||||||
|
@ -331,7 +468,7 @@ def _crash_handler(log_format):
|
||||||
return log_crash
|
return log_crash
|
||||||
|
|
||||||
|
|
||||||
def get_loglevel(loglevel):
|
def get_loglevel(loglevel: str) -> int:
|
||||||
""" Check whether a valid log level has been supplied, and return the numeric log level that
|
""" Check whether a valid log level has been supplied, and return the numeric log level that
|
||||||
corresponds to the given string level.
|
corresponds to the given string level.
|
||||||
|
|
||||||
|
@ -351,7 +488,7 @@ def get_loglevel(loglevel):
|
||||||
return numeric_level
|
return numeric_level
|
||||||
|
|
||||||
|
|
||||||
def crash_log():
|
def crash_log() -> str:
|
||||||
""" On a crash, write out the contents of :func:`_DEBUG_BUFFER` containing the last 100 lines
|
""" On a crash, write out the contents of :func:`_DEBUG_BUFFER` containing the last 100 lines
|
||||||
of debug messages to a crash report in the root Faceswap folder.
|
of debug messages to a crash report in the root Faceswap folder.
|
||||||
|
|
||||||
|
@ -379,11 +516,11 @@ def crash_log():
|
||||||
_OLD_FACTORY = logging.getLogRecordFactory()
|
_OLD_FACTORY = logging.getLogRecordFactory()
|
||||||
|
|
||||||
|
|
||||||
def _faceswap_logrecord(*args, **kwargs):
|
def _faceswap_logrecord(*args, **kwargs) -> logging.LogRecord:
|
||||||
""" Add a flag to :class:`logging.LogRecord` to not strip formatting from particular
|
""" Add a flag to :class:`logging.LogRecord` to not strip formatting from particular
|
||||||
records. """
|
records. """
|
||||||
record = _OLD_FACTORY(*args, **kwargs)
|
record = _OLD_FACTORY(*args, **kwargs)
|
||||||
record.strip_spaces = True
|
record.strip_spaces = True # type:ignore
|
||||||
return record
|
return record
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,6 @@ ffmpy==0.2.3
|
||||||
#nvidia-ml-py>=11.510,<300
|
#nvidia-ml-py>=11.510,<300
|
||||||
# Pin nvidida-ml-py to <11.515 until we know if bytes->str is an error or permanent change
|
# Pin nvidida-ml-py to <11.515 until we know if bytes->str is an error or permanent change
|
||||||
nvidia-ml-py<11.515
|
nvidia-ml-py<11.515
|
||||||
tensorflow_probability<0.17
|
tensorflow-probability<0.17
|
||||||
typing-extensions>=4.0.0
|
typing-extensions>=4.0.0
|
||||||
pywin32>=228 ; sys_platform == "win32"
|
pywin32>=228 ; sys_platform == "win32"
|
||||||
|
|
|
@ -16,6 +16,8 @@ ignore_missing_imports = True
|
||||||
ignore_missing_imports = True
|
ignore_missing_imports = True
|
||||||
[mypy-matplotlib.*]
|
[mypy-matplotlib.*]
|
||||||
ignore_missing_imports = True
|
ignore_missing_imports = True
|
||||||
|
[mypy-pexpect.*]
|
||||||
|
ignore_missing_imports = True
|
||||||
[mypy-PIL.*]
|
[mypy-PIL.*]
|
||||||
ignore_missing_imports = True
|
ignore_missing_imports = True
|
||||||
[mypy-plaidml.*]
|
[mypy-plaidml.*]
|
||||||
|
|
|
@ -3,30 +3,32 @@
|
||||||
|
|
||||||
Checks for installed Conda / Pip packages and updates accordingly
|
Checks for installed Conda / Pip packages and updates accordingly
|
||||||
"""
|
"""
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
from setup import Environment, Install, Output
|
from lib.logger import log_setup
|
||||||
|
from setup import Environment, Install
|
||||||
|
|
||||||
_LOGGER = None
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def output(msg):
|
def main(is_gui=False) -> None:
|
||||||
""" Output to print or logger """
|
""" Check for and update dependencies
|
||||||
if _LOGGER is not None:
|
|
||||||
_LOGGER.info(msg)
|
|
||||||
else:
|
|
||||||
Output().info(msg)
|
|
||||||
|
|
||||||
|
Parameters
|
||||||
def main(logger=None):
|
----------
|
||||||
""" Check for and update dependencies """
|
is_gui: bool, optional
|
||||||
if logger is not None:
|
``True`` if being called by the GUI. Prevents the updater from outputting progress bars
|
||||||
global _LOGGER # pylint:disable=global-statement
|
which get scrambled in the GUI
|
||||||
_LOGGER = logger
|
"""
|
||||||
output("Updating dependencies...")
|
logger.info("Updating dependencies...")
|
||||||
update = Environment(logger=logger, updater=True)
|
update = Environment(updater=True)
|
||||||
Install(update)
|
Install(update, is_gui=is_gui)
|
||||||
output("Dependencies updated")
|
logger.info("Dependencies updated")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
logfile = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), "faceswap_update.log")
|
||||||
|
log_setup("INFO", logfile, "setup")
|
||||||
main()
|
main()
|
||||||
|
|
Loading…
Add table
Reference in a new issue