Skip to content

Commit 6733e77

Browse files
committed
Merge remote-tracking branch 'a1111/dev' into dev-bluelovers
2 parents 8da9861 + 6685e53 commit 6733e77

25 files changed

+230
-68
lines changed

.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ module.exports = {
8888
// imageviewer.js
8989
modalPrevImage: "readonly",
9090
modalNextImage: "readonly",
91+
updateModalImageIfVisible: "readonly",
9192
// localStorage.js
9293
localSet: "readonly",
9394
localGet: "readonly",

.github/workflows/on_pull_request.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
- name: Install Ruff
2323
run: pip install ruff==0.3.3
2424
- name: Run Ruff
25-
run: ruff .
25+
run: ruff check .
2626
lint-js:
2727
name: eslint
2828
runs-on: ubuntu-latest

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ If your system is very new, you need to install python3.11 or python3.10:
133133
# Ubuntu 24.04
134134
sudo add-apt-repository ppa:deadsnakes/ppa
135135
sudo apt update
136-
sudo apt install python3.11
136+
sudo apt install python3.11 python3.11-venv
137137

138138
# Manjaro/Arch
139139
sudo pacman -S yay

extensions-builtin/prompt-bracket-checker/javascript/prompt-bracket-checker.js

Lines changed: 55 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,69 @@
1-
// Stable Diffusion WebUI - Bracket checker
2-
// By Hingashi no Florin/Bwin4L & @akx
1+
// Stable Diffusion WebUI - Bracket Checker
2+
// By @Bwin4L, @akx, @w-e-w, @Haoming02
33
// Counts open and closed brackets (round, square, curly) in the prompt and negative prompt text boxes in the txt2img and img2img tabs.
4-
// If there's a mismatch, the keyword counter turns red and if you hover on it, a tooltip tells you what's wrong.
4+
// If there's a mismatch, the keyword counter turns red, and if you hover on it, a tooltip tells you what's wrong.
5+
6+
function checkBrackets(textArea, counterElem) {
7+
const pairs = [
8+
['(', ')', 'round brackets'],
9+
['[', ']', 'square brackets'],
10+
['{', '}', 'curly brackets']
11+
];
512

6-
function checkBrackets(textArea, counterElt) {
713
const counts = {};
8-
textArea.value.matchAll(/(?<!\\)(?:\\\\)*?([(){}[\]])/g).forEach(bracket => {
9-
counts[bracket[1]] = (counts[bracket[1]] || 0) + 1;
10-
});
11-
const errors = [];
12-
13-
function checkPair(open, close, kind) {
14-
if (counts[open] !== counts[close]) {
15-
errors.push(
16-
`${open}...${close} - Detected ${counts[open] || 0} opening and ${counts[close] || 0} closing ${kind}.`
17-
);
14+
const errors = new Set();
15+
let i = 0;
16+
17+
while (i < textArea.value.length) {
18+
let char = textArea.value[i];
19+
let escaped = false;
20+
while (char === '\\' && i + 1 < textArea.value.length) {
21+
escaped = !escaped;
22+
i++;
23+
char = textArea.value[i];
24+
}
25+
26+
if (escaped) {
27+
i++;
28+
continue;
29+
}
30+
31+
for (const [open, close, label] of pairs) {
32+
if (char === open) {
33+
counts[label] = (counts[label] || 0) + 1;
34+
} else if (char === close) {
35+
counts[label] = (counts[label] || 0) - 1;
36+
if (counts[label] < 0) {
37+
errors.add(`Incorrect order of ${label}.`);
38+
}
39+
}
40+
}
41+
42+
i++;
43+
}
44+
45+
for (const [open, close, label] of pairs) {
46+
if (counts[label] == undefined) {
47+
continue;
48+
}
49+
50+
if (counts[label] > 0) {
51+
errors.add(`${open} ... ${close} - Detected ${counts[label]} more opening than closing ${label}.`);
52+
} else if (counts[label] < 0) {
53+
errors.add(`${open} ... ${close} - Detected ${-counts[label]} more closing than opening ${label}.`);
1854
}
1955
}
2056

21-
checkPair('(', ')', 'round brackets');
22-
checkPair('[', ']', 'square brackets');
23-
checkPair('{', '}', 'curly brackets');
24-
counterElt.title = errors.join('\n');
25-
counterElt.classList.toggle('error', errors.length !== 0);
57+
counterElem.title = [...errors].join('\n');
58+
counterElem.classList.toggle('error', errors.size !== 0);
2659
}
2760

2861
function setupBracketChecking(id_prompt, id_counter) {
29-
var textarea = gradioApp().querySelector("#" + id_prompt + " > label > textarea");
30-
var counter = gradioApp().getElementById(id_counter);
62+
const textarea = gradioApp().querySelector(`#${id_prompt} > label > textarea`);
63+
const counter = gradioApp().getElementById(id_counter);
3164

3265
if (textarea && counter) {
33-
textarea.addEventListener("input", () => checkBrackets(textarea, counter));
66+
onEdit(`${id_prompt}_BracketChecking`, textarea, 400, () => checkBrackets(textarea, counter));
3467
}
3568
}
3669

html/footer.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<div>
2-
<a href="{api_docs}">API</a>
2+
<a href="{api_docs}" target="_blank">API</a>
33
 • 
44
<a href="https://github.com/AUTOMATIC1111/stable-diffusion-webui">GitHub</a>
55
 • 

javascript/imageviewer.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ function updateOnBackgroundChange() {
5555
updateModalImage();
5656
}
5757
}
58+
const updateModalImageIfVisible = updateOnBackgroundChange;
5859

5960
function modalImageSwitch(offset) {
6061
var galleryButtons = all_gallery_buttons();
@@ -165,6 +166,7 @@ function modalLivePreviewToggle(event) {
165166
const modalToggleLivePreview = gradioApp().getElementById("modal_toggle_live_preview");
166167
opts.js_live_preview_in_modal_lightbox = !opts.js_live_preview_in_modal_lightbox;
167168
modalToggleLivePreview.innerHTML = opts.js_live_preview_in_modal_lightbox ? "&#x1F5C7;" : "&#x1F5C6;";
169+
updateModalImageIfVisible();
168170
event.stopPropagation();
169171
}
170172

javascript/progressbar.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ function requestProgress(id_task, progressbarContainer, gallery, atEnd, onProgre
190190
livePreview.className = 'livePreview';
191191
gallery.insertBefore(livePreview, gallery.firstElementChild);
192192
}
193-
193+
updateModalImageIfVisible();
194194
livePreview.appendChild(img);
195195
if (livePreview.childElementCount > 2) {
196196
livePreview.removeChild(livePreview.firstElementChild);

launch.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
index_url = launch_utils.index_url
77
dir_repos = launch_utils.dir_repos
88

9+
if args.uv:
10+
from modules.uv_hook import patch
11+
patch()
12+
13+
914
commit_hash = launch_utils.commit_hash
1015
git_tag = launch_utils.git_tag
1116

modules/cmd_args.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,4 @@
126126
parser.add_argument("--unix-filenames-sanitization", action='store_true', help="allow any symbols except '/' in filenames. May conflict with your browser and file system")
127127
parser.add_argument("--filenames-max-length", type=int, default=128, help='maximal length of filenames of saved images. If you override it, it can conflict with your file system')
128128
parser.add_argument("--no-prompt-history", action='store_true', help="disable read prompt from last generation feature; settings this argument will not create '--data_path/params.txt' file")
129+
parser.add_argument("--uv", action='store_true', help="use the uv package manager")

modules/hashes.py

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import hashlib
22
import os.path
33

4-
from modules import shared
4+
from modules import shared, errors
55
import modules.cache
66

77
dump_cache = modules.cache.dump_cache
@@ -32,7 +32,7 @@ def sha256_from_cache(filename, title, use_addnet_hash=False):
3232
cached_sha256 = hashes[title].get("sha256", None)
3333
cached_mtime = hashes[title].get("mtime", 0)
3434

35-
if ondisk_mtime > cached_mtime or cached_sha256 is None:
35+
if ondisk_mtime != cached_mtime or cached_sha256 is None:
3636
return None
3737

3838
return cached_sha256
@@ -82,3 +82,31 @@ def addnet_hash_safetensors(b):
8282

8383
return hash_sha256.hexdigest()
8484

85+
86+
def partial_hash_from_cache(filename, *, ignore_cache: bool = False, digits: int = 8):
87+
"""old hash that only looks at a small part of the file and is prone to collisions
88+
kept for compatibility, don't use this for new things
89+
"""
90+
try:
91+
filename = str(filename)
92+
mtime = os.path.getmtime(filename)
93+
hashes = cache('partial-hash')
94+
cache_entry = hashes.get(filename, {})
95+
cache_mtime = cache_entry.get("mtime", 0)
96+
cache_hash = cache_entry.get("hash", None)
97+
if mtime == cache_mtime and cache_hash and not ignore_cache:
98+
return cache_hash[0:digits]
99+
100+
with open(filename, 'rb') as file:
101+
m = hashlib.sha256()
102+
file.seek(0x100000)
103+
m.update(file.read(0x10000))
104+
partial_hash = m.hexdigest()
105+
hashes[filename] = {'mtime': mtime, 'hash': partial_hash}
106+
return partial_hash[0:digits]
107+
108+
except FileNotFoundError:
109+
pass
110+
except Exception:
111+
errors.report(f'Error calculating partial hash for {filename}', exc_info=True)
112+
return 'NOFILE'

0 commit comments

Comments
 (0)