Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Overbill1683
Stable Diffusion Webui
提交
1463cea9
S
Stable Diffusion Webui
项目概览
Overbill1683
/
Stable Diffusion Webui
10 个月 前同步成功
通知
1746
Star
81
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
分析
仓库
DevOps
项目成员
Pages
S
Stable Diffusion Webui
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Pages
分析
分析
仓库分析
DevOps
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
提交
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
1463cea9
编写于
11月 20, 2023
作者:
A
AUTOMATIC1111
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'dag' into dev
上级
73a0b4bb
9b471436
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
148 addition
and
153 deletion
+148
-153
modules/extensions.py
modules/extensions.py
+70
-62
modules/scripts.py
modules/scripts.py
+78
-91
未找到文件。
modules/extensions.py
浏览文件 @
1463cea9
from
__future__
import
annotations
import
configparser
import
configparser
import
functools
import
os
import
os
import
threading
import
threading
import
re
import
re
...
@@ -8,7 +9,6 @@ from modules import shared, errors, cache, scripts
...
@@ -8,7 +9,6 @@ from modules import shared, errors, cache, scripts
from
modules.gitpython_hack
import
Repo
from
modules.gitpython_hack
import
Repo
from
modules.paths_internal
import
extensions_dir
,
extensions_builtin_dir
,
script_path
# noqa: F401
from
modules.paths_internal
import
extensions_dir
,
extensions_builtin_dir
,
script_path
# noqa: F401
extensions
=
[]
os
.
makedirs
(
extensions_dir
,
exist_ok
=
True
)
os
.
makedirs
(
extensions_dir
,
exist_ok
=
True
)
...
@@ -22,13 +22,56 @@ def active():
...
@@ -22,13 +22,56 @@ def active():
return
[
x
for
x
in
extensions
if
x
.
enabled
]
return
[
x
for
x
in
extensions
if
x
.
enabled
]
class
ExtensionMetadata
:
filename
=
"metadata.ini"
config
:
configparser
.
ConfigParser
canonical_name
:
str
requires
:
list
def
__init__
(
self
,
path
,
canonical_name
):
self
.
config
=
configparser
.
ConfigParser
()
filepath
=
os
.
path
.
join
(
path
,
self
.
filename
)
if
os
.
path
.
isfile
(
filepath
):
try
:
self
.
config
.
read
(
filepath
)
except
Exception
:
errors
.
report
(
f
"Error reading
{
self
.
filename
}
for extension
{
canonical_name
}
."
,
exc_info
=
True
)
self
.
canonical_name
=
self
.
config
.
get
(
"Extension"
,
"Name"
,
fallback
=
canonical_name
)
self
.
canonical_name
=
canonical_name
.
lower
().
strip
()
self
.
requires
=
self
.
get_script_requirements
(
"Requires"
,
"Extension"
)
def
get_script_requirements
(
self
,
field
,
section
,
extra_section
=
None
):
"""reads a list of requirements from the config; field is the name of the field in the ini file,
like Requires or Before, and section is the name of the [section] in the ini file; additionally,
reads more requirements from [extra_section] if specified."""
x
=
self
.
config
.
get
(
section
,
field
,
fallback
=
''
)
if
extra_section
:
x
=
x
+
', '
+
self
.
config
.
get
(
extra_section
,
field
,
fallback
=
''
)
return
self
.
parse_list
(
x
.
lower
())
def
parse_list
(
self
,
text
):
"""converts a line from config ("ext1 ext2, ext3 ") into a python list (["ext1", "ext2", "ext3"])"""
if
not
text
:
return
[]
# both "," and " " are accepted as separator
return
[
x
for
x
in
re
.
split
(
r
"[,\s]+"
,
text
.
strip
())
if
x
]
class
Extension
:
class
Extension
:
lock
=
threading
.
Lock
()
lock
=
threading
.
Lock
()
cached_fields
=
[
'remote'
,
'commit_date'
,
'branch'
,
'commit_hash'
,
'version'
]
cached_fields
=
[
'remote'
,
'commit_date'
,
'branch'
,
'commit_hash'
,
'version'
]
metadata
:
ExtensionMetadata
def
__init__
(
self
,
name
,
path
,
enabled
=
True
,
is_builtin
=
False
,
canonical_name
=
None
):
def
__init__
(
self
,
name
,
path
,
enabled
=
True
,
is_builtin
=
False
,
metadata
=
None
):
self
.
name
=
name
self
.
name
=
name
self
.
canonical_name
=
canonical_name
or
name
.
lower
()
self
.
path
=
path
self
.
path
=
path
self
.
enabled
=
enabled
self
.
enabled
=
enabled
self
.
status
=
''
self
.
status
=
''
...
@@ -40,18 +83,8 @@ class Extension:
...
@@ -40,18 +83,8 @@ class Extension:
self
.
branch
=
None
self
.
branch
=
None
self
.
remote
=
None
self
.
remote
=
None
self
.
have_info_from_repo
=
False
self
.
have_info_from_repo
=
False
self
.
metadata
=
metadata
if
metadata
else
ExtensionMetadata
(
self
.
path
,
name
.
lower
())
@
functools
.
cached_property
self
.
canonical_name
=
metadata
.
canonical_name
def
metadata
(
self
):
if
os
.
path
.
isfile
(
os
.
path
.
join
(
self
.
path
,
"metadata.ini"
)):
try
:
config
=
configparser
.
ConfigParser
()
config
.
read
(
os
.
path
.
join
(
self
.
path
,
"metadata.ini"
))
return
config
except
Exception
:
errors
.
report
(
f
"Error reading metadata.ini for extension
{
self
.
canonical_name
}
."
,
exc_info
=
True
)
return
None
def
to_dict
(
self
):
def
to_dict
(
self
):
return
{
x
:
getattr
(
self
,
x
)
for
x
in
self
.
cached_fields
}
return
{
x
:
getattr
(
self
,
x
)
for
x
in
self
.
cached_fields
}
...
@@ -162,7 +195,7 @@ def list_extensions():
...
@@ -162,7 +195,7 @@ def list_extensions():
elif
shared
.
opts
.
disable_all_extensions
==
"extra"
:
elif
shared
.
opts
.
disable_all_extensions
==
"extra"
:
print
(
"***
\"
Disable all extensions
\"
option was set, will only load built-in extensions ***"
)
print
(
"***
\"
Disable all extensions
\"
option was set, will only load built-in extensions ***"
)
extension_dependency_map
=
{}
loaded_extensions
=
{}
# scan through extensions directory and load metadata
# scan through extensions directory and load metadata
for
dirname
in
[
extensions_builtin_dir
,
extensions_dir
]:
for
dirname
in
[
extensions_builtin_dir
,
extensions_dir
]:
...
@@ -175,55 +208,30 @@ def list_extensions():
...
@@ -175,55 +208,30 @@ def list_extensions():
continue
continue
canonical_name
=
extension_dirname
canonical_name
=
extension_dirname
requires
=
None
metadata
=
ExtensionMetadata
(
path
,
canonical_name
)
if
os
.
path
.
isfile
(
os
.
path
.
join
(
path
,
"metadata.ini"
)):
# check for duplicated canonical names
try
:
already_loaded_extension
=
loaded_extensions
.
get
(
metadata
.
canonical_name
)
config
=
configparser
.
ConfigParser
()
if
already_loaded_extension
is
not
None
:
config
.
read
(
os
.
path
.
join
(
path
,
"metadata.ini"
))
errors
.
report
(
f
'Duplicate canonical name "
{
canonical_name
}
" found in extensions "
{
extension_dirname
}
" and "
{
already_loaded_extension
.
name
}
". Former will be discarded.'
,
exc_info
=
False
)
canonical_name
=
config
.
get
(
"Extension"
,
"Name"
,
fallback
=
canonical_name
)
continue
requires
=
config
.
get
(
"Extension"
,
"Requires"
,
fallback
=
None
)
except
Exception
:
errors
.
report
(
f
"Error reading metadata.ini for extension
{
extension_dirname
}
. "
f
"Will load regardless."
,
exc_info
=
True
)
canonical_name
=
canonical_name
.
lower
().
strip
()
is_builtin
=
dirname
==
extensions_builtin_dir
extension
=
Extension
(
name
=
extension_dirname
,
path
=
path
,
enabled
=
extension_dirname
not
in
shared
.
opts
.
disabled_extensions
,
is_builtin
=
is_builtin
,
metadata
=
metadata
)
extensions
.
append
(
extension
)
loaded_extensions
[
canonical_name
]
=
extension
# check for duplicated canonical names
# check for requirements
if
canonical_name
in
extension_dependency_map
:
for
extension
in
extensions
:
errors
.
report
(
f
"Duplicate canonical name
\"
{
canonical_name
}
\"
found in extensions "
for
req
in
extension
.
metadata
.
requires
:
f
"
\"
{
extension_dirname
}
\"
and
\"
{
extension_dependency_map
[
canonical_name
][
'dirname'
]
}
\"
. "
required_extension
=
loaded_extensions
.
get
(
req
)
f
"The current loading extension will be discarded."
,
exc_info
=
False
)
if
required_extension
is
None
:
errors
.
report
(
f
'Extension "
{
extension
.
name
}
" requires "
{
req
}
" which is not installed.'
,
exc_info
=
False
)
continue
continue
# both "," and " " are accepted as separator
if
not
extension
.
enabled
:
requires
=
list
(
filter
(
None
,
re
.
split
(
r
"[,\s]+"
,
requires
.
lower
())))
if
requires
else
[]
errors
.
report
(
f
'Extension "
{
extension
.
name
}
" requires "
{
required_extension
.
name
}
" which is disabled.'
,
exc_info
=
False
)
continue
extension_dependency_map
[
canonical_name
]
=
{
"dirname"
:
extension_dirname
,
"path"
:
path
,
"requires"
:
requires
,
}
# check for requirements
extensions
:
list
[
Extension
]
=
[]
for
(
_
,
extension_data
)
in
extension_dependency_map
.
items
():
dirname
,
path
,
requires
=
extension_data
[
'dirname'
],
extension_data
[
'path'
],
extension_data
[
'requires'
]
requirement_met
=
True
for
req
in
requires
:
if
req
not
in
extension_dependency_map
:
errors
.
report
(
f
"Extension
\"
{
dirname
}
\"
requires
\"
{
req
}
\"
which is not installed. "
f
"The current loading extension will be discarded."
,
exc_info
=
False
)
requirement_met
=
False
break
dep_dirname
=
extension_dependency_map
[
req
][
'dirname'
]
if
dep_dirname
in
shared
.
opts
.
disabled_extensions
:
errors
.
report
(
f
"Extension
\"
{
dirname
}
\"
requires
\"
{
dep_dirname
}
\"
which is disabled. "
f
"The current loading extension will be discarded."
,
exc_info
=
False
)
requirement_met
=
False
break
is_builtin
=
dirname
==
extensions_builtin_dir
extension
=
Extension
(
name
=
dirname
,
path
=
path
,
enabled
=
dirname
not
in
shared
.
opts
.
disabled_extensions
and
requirement_met
,
is_builtin
=
is_builtin
)
extensions
.
append
(
extension
)
modules/scripts.py
浏览文件 @
1463cea9
...
@@ -2,7 +2,6 @@ import os
...
@@ -2,7 +2,6 @@ import os
import
re
import
re
import
sys
import
sys
import
inspect
import
inspect
from
graphlib
import
TopologicalSorter
,
CycleError
from
collections
import
namedtuple
from
collections
import
namedtuple
from
dataclasses
import
dataclass
from
dataclasses
import
dataclass
...
@@ -312,27 +311,57 @@ scripts_data = []
...
@@ -312,27 +311,57 @@ scripts_data = []
postprocessing_scripts_data
=
[]
postprocessing_scripts_data
=
[]
ScriptClassData
=
namedtuple
(
"ScriptClassData"
,
[
"script_class"
,
"path"
,
"basedir"
,
"module"
])
ScriptClassData
=
namedtuple
(
"ScriptClassData"
,
[
"script_class"
,
"path"
,
"basedir"
,
"module"
])
def
topological_sort
(
dependencies
):
"""Accepts a dictionary mapping name to its dependencies, returns a list of names ordered according to dependencies.
Ignores errors relating to missing dependeencies or circular dependencies
"""
visited
=
{}
result
=
[]
def
inner
(
name
):
visited
[
name
]
=
True
for
dep
in
dependencies
.
get
(
name
,
[]):
if
dep
in
dependencies
and
dep
not
in
visited
:
inner
(
dep
)
result
.
append
(
name
)
for
depname
in
dependencies
:
if
depname
not
in
visited
:
inner
(
depname
)
return
result
@
dataclass
class
ScriptWithDependencies
:
script_canonical_name
:
str
file
:
ScriptFile
requires
:
list
load_before
:
list
load_after
:
list
def
list_scripts
(
scriptdirname
,
extension
,
*
,
include_extensions
=
True
):
def
list_scripts
(
scriptdirname
,
extension
,
*
,
include_extensions
=
True
):
scripts_list
=
[]
scripts
=
{}
script_dependency_map
=
{}
# build script dependency map
loaded_extensions
=
{
ext
.
canonical_name
:
ext
for
ext
in
extensions
.
active
()}
loaded_extensions_scripts
=
{
ext
.
canonical_name
:
[]
for
ext
in
extensions
.
active
()}
# build script dependency map
root_script_basedir
=
os
.
path
.
join
(
paths
.
script_path
,
scriptdirname
)
root_script_basedir
=
os
.
path
.
join
(
paths
.
script_path
,
scriptdirname
)
if
os
.
path
.
exists
(
root_script_basedir
):
if
os
.
path
.
exists
(
root_script_basedir
):
for
filename
in
sorted
(
os
.
listdir
(
root_script_basedir
)):
for
filename
in
sorted
(
os
.
listdir
(
root_script_basedir
)):
if
not
os
.
path
.
isfile
(
os
.
path
.
join
(
root_script_basedir
,
filename
)):
if
not
os
.
path
.
isfile
(
os
.
path
.
join
(
root_script_basedir
,
filename
)):
continue
continue
script_dependency_map
[
filename
]
=
{
if
os
.
path
.
splitext
(
filename
)[
1
].
lower
()
!=
extension
:
"extension"
:
None
,
continue
"extension_dirname"
:
None
,
"script_file"
:
ScriptFile
(
paths
.
script_path
,
filename
,
os
.
path
.
join
(
root_script_basedir
,
filename
)),
script_file
=
ScriptFile
(
paths
.
script_path
,
filename
,
os
.
path
.
join
(
root_script_basedir
,
filename
))
"requires"
:
[],
scripts
[
filename
]
=
ScriptWithDependencies
(
filename
,
script_file
,
[],
[],
[])
"load_before"
:
[],
"load_after"
:
[],
}
if
include_extensions
:
if
include_extensions
:
for
ext
in
extensions
.
active
():
for
ext
in
extensions
.
active
():
...
@@ -341,96 +370,54 @@ def list_scripts(scriptdirname, extension, *, include_extensions=True):
...
@@ -341,96 +370,54 @@ def list_scripts(scriptdirname, extension, *, include_extensions=True):
if
not
os
.
path
.
isfile
(
extension_script
.
path
):
if
not
os
.
path
.
isfile
(
extension_script
.
path
):
continue
continue
script_canonical_name
=
ext
.
canonical_name
+
"/"
+
extension_script
.
filename
script_canonical_name
=
(
"builtin/"
if
ext
.
is_builtin
else
""
)
+
ext
.
canonical_name
+
"/"
+
extension_script
.
filename
if
ext
.
is_builtin
:
script_canonical_name
=
"builtin/"
+
script_canonical_name
relative_path
=
scriptdirname
+
"/"
+
extension_script
.
filename
relative_path
=
scriptdirname
+
"/"
+
extension_script
.
filename
requires
=
''
script
=
ScriptWithDependencies
(
load_before
=
''
script_canonical_name
=
script_canonical_name
,
load_after
=
''
file
=
extension_script
,
requires
=
ext
.
metadata
.
get_script_requirements
(
"Requires"
,
relative_path
,
scriptdirname
),
if
ext
.
metadata
is
not
None
:
load_before
=
ext
.
metadata
.
get_script_requirements
(
"Before"
,
relative_path
,
scriptdirname
),
requires
=
ext
.
metadata
.
get
(
relative_path
,
"Requires"
,
fallback
=
''
)
load_after
=
ext
.
metadata
.
get_script_requirements
(
"After"
,
relative_path
,
scriptdirname
),
load_before
=
ext
.
metadata
.
get
(
relative_path
,
"Before"
,
fallback
=
''
)
)
load_after
=
ext
.
metadata
.
get
(
relative_path
,
"After"
,
fallback
=
''
)
# propagate directory level metadata
requires
=
requires
+
','
+
ext
.
metadata
.
get
(
scriptdirname
,
"Requires"
,
fallback
=
''
)
load_before
=
load_before
+
','
+
ext
.
metadata
.
get
(
scriptdirname
,
"Before"
,
fallback
=
''
)
load_after
=
load_after
+
','
+
ext
.
metadata
.
get
(
scriptdirname
,
"After"
,
fallback
=
''
)
requires
=
list
(
filter
(
None
,
re
.
split
(
r
"[,\s]+"
,
requires
.
lower
())))
if
requires
else
[]
load_after
=
list
(
filter
(
None
,
re
.
split
(
r
"[,\s]+"
,
load_after
.
lower
())))
if
load_after
else
[]
load_before
=
list
(
filter
(
None
,
re
.
split
(
r
"[,\s]+"
,
load_before
.
lower
())))
if
load_before
else
[]
script_dependency_map
[
script_canonical_name
]
=
{
"extension"
:
ext
.
canonical_name
,
"extension_dirname"
:
ext
.
name
,
"script_file"
:
extension_script
,
"requires"
:
requires
,
"load_before"
:
load_before
,
"load_after"
:
load_after
,
}
# resolve dependencies
scripts
[
script_canonical_name
]
=
script
loaded_extensions_scripts
[
ext
.
canonical_name
].
append
(
script
)
loaded_extensions
=
set
()
for
script_canonical_name
,
script
in
scripts
.
items
():
for
ext
in
extensions
.
active
():
loaded_extensions
.
add
(
ext
.
canonical_name
)
for
script_canonical_name
,
script_data
in
script_dependency_map
.
items
():
# load before requires inverse dependency
# load before requires inverse dependency
# in this case, append the script name into the load_after list of the specified script
# in this case, append the script name into the load_after list of the specified script
for
load_before
_script
in
script_data
[
'load_before'
]
:
for
load_before
in
script
.
load_before
:
# if this requires an individual script to be loaded before
# if this requires an individual script to be loaded before
if
load_before_script
in
script_dependency_map
:
other_script
=
scripts
.
get
(
load_before
)
script_dependency_map
[
load_before_script
][
'load_after'
].
append
(
script_canonical_name
)
if
other_script
:
elif
load_before_script
in
loaded_extensions
:
other_script
.
load_after
.
append
(
script_canonical_name
)
for
_
,
script_data2
in
script_dependency_map
.
items
():
if
script_data2
[
'extension'
]
==
load_before_script
:
script_data2
[
'load_after'
].
append
(
script_canonical_name
)
break
# resolve extension name in load_after lists
for
load_after_script
in
list
(
script_data
[
'load_after'
]):
if
load_after_script
not
in
script_dependency_map
and
load_after_script
in
loaded_extensions
:
script_data
[
'load_after'
].
remove
(
load_after_script
)
for
script_canonical_name2
,
script_data2
in
script_dependency_map
.
items
():
if
script_data2
[
'extension'
]
==
load_after_script
:
script_data
[
'load_after'
].
append
(
script_canonical_name2
)
break
# build the DAG
sorter
=
TopologicalSorter
()
for
script_canonical_name
,
script_data
in
script_dependency_map
.
items
():
requirement_met
=
True
for
required_script
in
script_data
[
'requires'
]:
# if this requires an individual script to be loaded
if
required_script
not
in
script_dependency_map
and
required_script
not
in
loaded_extensions
:
errors
.
report
(
f
"Script
\"
{
script_canonical_name
}
\"
"
f
"requires
\"
{
required_script
}
\"
to "
f
"be loaded, but it is not. Skipping."
,
exc_info
=
False
)
requirement_met
=
False
break
if
not
requirement_met
:
continue
sorter
.
add
(
script_canonical_name
,
*
script_data
[
'load_after'
])
# if this requires an extension
other_extension_scripts
=
loaded_extensions_scripts
.
get
(
load_before
)
if
other_extension_scripts
:
for
other_script
in
other_extension_scripts
:
other_script
.
load_after
.
append
(
script_canonical_name
)
# sort the scripts
# if After mentions an extension, remove it and instead add all of its scripts
try
:
for
load_after
in
list
(
script
.
load_after
):
ordered_script
=
sorter
.
static_order
()
if
load_after
not
in
scripts
and
load_after
in
loaded_extensions_scripts
:
except
CycleError
:
script
.
load_after
.
remove
(
load_after
)
errors
.
report
(
"Cycle detected in script dependencies. Scripts will load in ascending order."
,
exc_info
=
True
)
ordered_script
=
script_dependency_map
.
keys
()
for
other_script
in
loaded_extensions_scripts
.
get
(
load_after
,
[]):
script
.
load_after
.
append
(
other_script
.
script_canonical_name
)
dependencies
=
{}
for
script_canonical_name
,
script
in
scripts
.
items
():
for
required_script
in
script
.
requires
:
if
required_script
not
in
scripts
and
required_script
not
in
loaded_extensions
:
errors
.
report
(
f
'Script "
{
script_canonical_name
}
" requires "
{
required_script
}
" to be loaded, but it is not.'
,
exc_info
=
False
)
for
script_canonical_name
in
ordered_script
:
dependencies
[
script_canonical_name
]
=
script
.
load_after
script_data
=
script_dependency_map
[
script_canonical_name
]
scripts_list
.
append
(
script_data
[
'script_file'
])
scripts_list
=
[
x
for
x
in
scripts_list
if
os
.
path
.
splitext
(
x
.
path
)[
1
].
lower
()
==
extension
and
os
.
path
.
isfile
(
x
.
path
)]
ordered_scripts
=
topological_sort
(
dependencies
)
scripts_list
=
[
scripts
[
script_canonical_name
].
file
for
script_canonical_name
in
ordered_scripts
]
return
scripts_list
return
scripts_list
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录