mirror of
https://github.com/vladmandic/automatic
synced 2026-09-19 09:14:35 +02:00
Merge pull request #4505 from awsr/time-fixes
Functionality update to extensions handling
This commit is contained in:
+28
-4
@@ -1,6 +1,6 @@
|
||||
from __future__ import annotations
|
||||
import os
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
import git
|
||||
from modules import shared, errors
|
||||
from modules.paths import extensions_dir, extensions_builtin_dir
|
||||
@@ -11,6 +11,30 @@ if not os.path.exists(extensions_dir):
|
||||
os.makedirs(extensions_dir)
|
||||
|
||||
|
||||
def parse_isotime(time_string: str) -> datetime:
|
||||
# If Python minimum version is 3.11+, this function can be replaced with datetime.fromisoformat()
|
||||
trimmed = time_string.rstrip("Z")
|
||||
if "." in trimmed:
|
||||
trimmed = trimmed.split(".")[0]
|
||||
match len(trimmed):
|
||||
case 16:
|
||||
return datetime.strptime(trimmed, "%Y-%m-%dT%H:%M").replace(tzinfo=timezone.utc)
|
||||
case 19:
|
||||
return datetime.strptime(trimmed, "%Y-%m-%dT%H:%M:%S").replace(tzinfo=timezone.utc)
|
||||
case _:
|
||||
raise ValueError(f"Unexpected time string format: '{time_string}'")
|
||||
|
||||
|
||||
def format_dt(d: datetime) -> str:
|
||||
if d.tzinfo is None:
|
||||
return d.strftime('%Y-%m-%d %H:%M')
|
||||
return d.astimezone(timezone.utc).strftime('%Y-%m-%d %H:%M:%S') # Ensure UTC time is shown (just in case)
|
||||
|
||||
|
||||
def ts2utc(timestamp: int) -> datetime:
|
||||
return datetime.fromtimestamp(timestamp, timezone.utc)
|
||||
|
||||
|
||||
def active():
|
||||
if shared.opts.disable_all_extensions == "all":
|
||||
return []
|
||||
@@ -106,8 +130,8 @@ class Extension:
|
||||
self.branch = None
|
||||
self.remote = None
|
||||
self.have_info_from_repo = False
|
||||
self.mtime = 0
|
||||
self.ctime = 0
|
||||
self.mtime = "2000-01-01T00:00Z"
|
||||
self.ctime = "2000-01-01T00:00Z"
|
||||
|
||||
def read_info(self, force=False):
|
||||
if self.have_info_from_repo and not force:
|
||||
@@ -142,7 +166,7 @@ class Extension:
|
||||
except Exception:
|
||||
self.branch = 'unknown'
|
||||
self.commit_hash = head.hexsha
|
||||
self.version = f"<p>{self.commit_hash[:8]}</p><p>{datetime.fromtimestamp(self.commit_date).strftime('%a %b%d %Y %H:%M')}</p>"
|
||||
self.version = f"<p>{self.commit_hash[:8]}</p><p>{format_dt(ts2utc(self.commit_date))}</p>"
|
||||
except Exception as ex:
|
||||
shared.log.error(f"Extension: failed reading data from git repo={self.name}: {ex}")
|
||||
self.remote = None
|
||||
|
||||
+18
-20
@@ -3,7 +3,7 @@ import json
|
||||
import shutil
|
||||
import errno
|
||||
import html
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timezone, timedelta
|
||||
import gradio as gr
|
||||
from modules import extensions, shared, paths, errors, ui_symbols, call_queue
|
||||
|
||||
@@ -37,12 +37,9 @@ def get_installed(ext):
|
||||
def list_extensions():
|
||||
global extensions_list # pylint: disable=global-statement
|
||||
fn = os.path.join(paths.script_path, "html", "extensions.json")
|
||||
extensions_list = shared.readfile(fn, silent=True) or []
|
||||
if type(extensions_list) != list:
|
||||
shared.log.warning(f'Invalid extensions list: file="{fn}"')
|
||||
extensions_list = []
|
||||
extensions_list = shared.readfile(fn, silent=True, as_type="list")
|
||||
if len(extensions_list) == 0:
|
||||
shared.log.info('Extension list is empty: refresh required')
|
||||
shared.log.info("Extension List: No information found. Refresh required.")
|
||||
found = []
|
||||
for ext in extensions.extensions:
|
||||
ext.read_info()
|
||||
@@ -111,10 +108,10 @@ def check_updates(_id_task, disable_list, search_text, sort_column):
|
||||
ext.git_fetch()
|
||||
ext.read_info()
|
||||
commit_date = ext.commit_date or 1577836800
|
||||
shared.log.info(f'Extensions updated: {ext.name} {ext.commit_hash[:8]} {datetime.utcfromtimestamp(commit_date)}')
|
||||
shared.log.info(f'Extensions updated: {ext.name} {ext.commit_hash[:8]} {extensions.format_dt(extensions.ts2utc(commit_date))}')
|
||||
else:
|
||||
commit_date = ext.commit_date or 1577836800
|
||||
shared.log.debug(f'Extensions no update available: {ext.name} {ext.commit_hash[:8]} {datetime.utcfromtimestamp(commit_date)}')
|
||||
shared.log.debug(f'Extensions no update available: {ext.name} {ext.commit_hash[:8]} {extensions.format_dt(extensions.ts2utc(commit_date))}')
|
||||
except FileNotFoundError as e:
|
||||
if 'FETCH_HEAD' not in str(e):
|
||||
raise
|
||||
@@ -232,10 +229,10 @@ def update_extension(extension_path, search_text, sort_column):
|
||||
ext.git_fetch()
|
||||
ext.read_info()
|
||||
commit_date = ext.commit_date or 1577836800
|
||||
shared.log.info(f'Extensions updated: {ext.name} {ext.commit_hash[:8]} {datetime.utcfromtimestamp(commit_date)}')
|
||||
shared.log.info(f'Extensions updated: {ext.name} {ext.commit_hash[:8]} {extensions.format_dt(extensions.ts2utc(commit_date))}')
|
||||
else:
|
||||
commit_date = ext.commit_date or 1577836800
|
||||
shared.log.info(f'Extensions no update available: {ext.name} {ext.commit_hash[:8]} {datetime.utcfromtimestamp(commit_date)}')
|
||||
shared.log.info(f'Extensions no update available: {ext.name} {ext.commit_hash[:8]} {extensions.format_dt(extensions.ts2utc(commit_date))}')
|
||||
except FileNotFoundError as e:
|
||||
if 'FETCH_HEAD' not in str(e):
|
||||
raise
|
||||
@@ -308,13 +305,13 @@ def create_html(search_text, sort_column):
|
||||
ext['enabled'] = installed.enabled if installed is not None else ''
|
||||
ext['remote'] = installed.remote if installed is not None else None
|
||||
ext['path'] = installed.path if installed is not None else ''
|
||||
ext['sort_default'] = f"{'1' if ext['is_builtin'] else '0'}{'1' if ext['installed'] else '0'}{ext.get('updated', '2000-01-01T00:00')}"
|
||||
ext['sort_default'] = f"{'1' if ext['is_builtin'] else '0'}{'1' if ext['installed'] else '0'}{ext.get('updated', '2000-01-01T00:00Z')}"
|
||||
sort_reverse, sort_function = sort_ordering[sort_column]
|
||||
|
||||
def dt(x: str):
|
||||
val = ext.get(x, None)
|
||||
try:
|
||||
return datetime.fromisoformat(val[:-1]).strftime('%a %b%d %Y %H:%M') if val is not None else "N/A"
|
||||
return extensions.format_dt(extensions.parse_isotime(val)) if val is not None else "N/A"
|
||||
except Exception:
|
||||
return 'N/A'
|
||||
|
||||
@@ -322,22 +319,23 @@ def create_html(search_text, sort_column):
|
||||
for ext in sorted(extensions_list, key=sort_function, reverse=sort_reverse):
|
||||
installed = get_installed(ext)
|
||||
author = ''
|
||||
updated = datetime.timestamp(datetime.now())
|
||||
updated = datetime.now(timezone.utc) # TZ-aware
|
||||
try:
|
||||
if 'github' in ext['url']:
|
||||
author = 'Author: ' + ext['url'].split('/')[-2].split(':')[-1] if '/' in ext['url'] else ext['url'].split(':')[1].split('/')[0]
|
||||
updated = datetime.timestamp(datetime.fromisoformat(ext.get('updated', '2000-01-01T00:00:00.000Z').rstrip('Z')))
|
||||
updated = extensions.parse_isotime(ext.get('updated', '2000-01-01T00:00:00Z')) # TZ-aware
|
||||
else:
|
||||
debug(f'Extension not from github: name={ext["name"]} url={ext["url"]}')
|
||||
except Exception as e:
|
||||
debug(f'Extension get updated error: name={ext["name"]} url={ext["url"]} {e}')
|
||||
update_available = (installed is not None) and (ext['remote'] is not None) and (updated > ext['commit_date'])
|
||||
local_ver_date = extensions.ts2utc(ext['commit_date']) # TZ-aware
|
||||
update_available = (installed is not None) and (not ext['is_builtin']) and (ext['remote'] is not None) and (updated > local_ver_date) # TZ-aware
|
||||
if update_available:
|
||||
debug(f'Extension update available: name={ext["name"]} updated={updated}/{datetime.utcfromtimestamp(updated)} commit={ext["commit_date"]}/{datetime.utcfromtimestamp(ext["commit_date"])}')
|
||||
debug(f'Extension update available: name={ext["name"]} updated={extensions.format_dt(updated)} commit={extensions.format_dt(local_ver_date)}') # TZ-aware
|
||||
ext['sort_user'] = f"{'0' if ext['is_builtin'] else '1'}{'1' if ext['installed'] else '0'}{ext.get('name', '')}"
|
||||
ext['sort_enabled'] = f"{'0' if ext['enabled'] else '1'}{'1' if ext['is_builtin'] else '0'}{'1' if ext['installed'] else '0'}{ext.get('updated', '2000-01-01T00:00')}"
|
||||
ext['sort_update'] = f"{'1' if update_available else '0'}{'1' if ext['installed'] else '0'}{ext.get('updated', '2000-01-01T00:00')}"
|
||||
delta = datetime.now() - datetime.fromisoformat(ext.get('created', '2000-01-01T00:00Z')[:-1])
|
||||
ext['sort_enabled'] = f"{'0' if ext['enabled'] else '1'}{'1' if ext['is_builtin'] else '0'}{'1' if ext['installed'] else '0'}{ext.get('updated', '2000-01-01T00:00Z')}"
|
||||
ext['sort_update'] = f"{'1' if update_available else '0'}{'1' if ext['installed'] else '0'}{ext.get('updated', '2000-01-01T00:00Z')}"
|
||||
delta = datetime.now(timezone.utc) - extensions.parse_isotime(ext.get('created', '2000-01-01T00:00Z')) # TZ-aware to prep for 3.11+ datetime.fromisoformat() behavior
|
||||
ext['sort_trending'] = round(ext.get('stars', 0) / max(delta.days, 5), 1)
|
||||
tags = ext.get("tags", [])
|
||||
if not isinstance(tags, list):
|
||||
@@ -399,7 +397,7 @@ def create_html(search_text, sort_column):
|
||||
else:
|
||||
status = f"<div style='cursor:help;width:1em;' title='Unknown status'>{ui_symbols.svg_bullet.color('#008EBC')}</div>"
|
||||
else:
|
||||
if updated < datetime.timestamp(datetime.now() - timedelta(6*30)):
|
||||
if updated < datetime.now(timezone.utc) - timedelta(6*30): # TZ-aware
|
||||
status = f"<div style='cursor:help;width:1em;' title='Unmaintained'>{ui_symbols.svg_bullet.color('#C000CF')}</div>"
|
||||
else:
|
||||
status = f"<div style='cursor:help;width:1em;' title='No info'>{ui_symbols.svg_bullet.color('#7C7C7C')}</div>"
|
||||
|
||||
Reference in New Issue
Block a user