Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
avocado
提交
361948f3
A
avocado
项目概览
openeuler
/
avocado
通知
0
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
A
avocado
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
361948f3
编写于
6月 12, 2015
作者:
L
Lucas Meneghel Rodrigues
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'ldoktor-mux-tree4'
上级
97387080
ec2ee1c2
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
200 addition
and
104 deletion
+200
-104
avocado/core/plugins/multiplexer.py
avocado/core/plugins/multiplexer.py
+60
-25
avocado/core/plugins/runner.py
avocado/core/plugins/runner.py
+3
-1
avocado/core/tree.py
avocado/core/tree.py
+116
-66
etc/avocado/avocado.conf
etc/avocado/avocado.conf
+2
-0
selftests/all/functional/avocado/multiplex_tests.py
selftests/all/functional/avocado/multiplex_tests.py
+7
-6
selftests/all/unit/avocado/tree_unittest.py
selftests/all/unit/avocado/tree_unittest.py
+12
-6
未找到文件。
avocado/core/plugins/multiplexer.py
浏览文件 @
361948f3
...
...
@@ -14,11 +14,12 @@
import
sys
from
.
import
plugin
from
..
import
output
from
..
import
multiplexer
from
..
import
exit_codes
from
..
import
output
from
..
import
tree
from
..
import
multiplexer
from
.
import
plugin
from
..settings
import
settings
class
Multiplexer
(
plugin
.
Plugin
):
...
...
@@ -30,6 +31,10 @@ class Multiplexer(plugin.Plugin):
name
=
'multiplexer'
enabled
=
True
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
(
Multiplexer
,
self
).
__init__
(
*
args
,
**
kwargs
)
self
.
_from_args_tree
=
tree
.
TreeNode
()
def
configure
(
self
,
parser
):
if
multiplexer
.
MULTIPLEX_CAPABLE
is
False
:
self
.
enabled
=
False
...
...
@@ -45,18 +50,25 @@ class Multiplexer(plugin.Plugin):
self
.
parser
.
add_argument
(
'--filter-out'
,
nargs
=
'*'
,
default
=
[],
help
=
'Filter out path(s) from multiplexing'
)
self
.
parser
.
add_argument
(
'-t'
,
'--tree'
,
action
=
'store_true'
,
default
=
False
,
help
=
'Shows the multiplex tree structure'
)
self
.
parser
.
add_argument
(
'--attr'
,
nargs
=
'*'
,
default
=
[],
help
=
"Which attributes to show when using "
"--tree (default is 'name')"
)
self
.
parser
.
add_argument
(
'-c'
,
'--contents'
,
action
=
'store_true'
,
default
=
False
,
help
=
"Shows the variant content (variables)"
)
self
.
parser
.
add_argument
(
'-d'
,
'--debug'
,
action
=
'store_true'
,
default
=
False
,
help
=
"Debug multiplexed "
"files."
)
self
.
parser
.
add_argument
(
'--env'
,
default
=
[],
nargs
=
'*'
)
self
.
parser
.
add_argument
(
'-s'
,
'--system-wide'
,
action
=
'store_true'
,
help
=
"Combine the files with the default "
"tree."
)
self
.
parser
.
add_argument
(
'-c'
,
'--contents'
,
action
=
'store_true'
,
default
=
False
,
help
=
"Shows the node content "
"(variables)"
)
self
.
parser
.
add_argument
(
'--env'
,
default
=
[],
nargs
=
'*'
,
help
=
"Inject [path:]key:node values into "
"the final multiplex tree."
)
env_parser
=
self
.
parser
.
add_argument_group
(
"environment view options"
)
env_parser
.
add_argument
(
'-d'
,
'--debug'
,
action
=
'store_true'
,
default
=
False
,
help
=
"Debug multiplexed "
"files."
)
tree_parser
=
self
.
parser
.
add_argument_group
(
"tree view options"
)
tree_parser
.
add_argument
(
'-t'
,
'--tree'
,
action
=
'store_true'
,
default
=
False
,
help
=
'Shows the multiplex '
'tree structure'
)
tree_parser
.
add_argument
(
'-i'
,
'--inherit'
,
action
=
"store_true"
,
help
=
"Show the inherited values"
)
super
(
Multiplexer
,
self
).
configure
(
self
.
parser
)
def
activate
(
self
,
args
):
...
...
@@ -67,13 +79,22 @@ class Multiplexer(plugin.Plugin):
raise
ValueError
(
"key:value pairs required, found only %s"
%
(
value
))
elif
len
(
value
)
==
2
:
args
.
default_multiplex
_tree
.
value
[
value
[
0
]]
=
value
[
1
]
self
.
_from_args
_tree
.
value
[
value
[
0
]]
=
value
[
1
]
else
:
node
=
args
.
default_multiplex
_tree
.
get_node
(
value
[
0
],
True
)
node
=
self
.
_from_args
_tree
.
get_node
(
value
[
0
],
True
)
node
.
value
[
value
[
1
]]
=
value
[
2
]
def
run
(
self
,
args
):
view
=
output
.
View
(
app_args
=
args
)
err
=
None
if
args
.
tree
and
args
.
debug
:
err
=
"Option --tree is incompatible with --debug."
elif
not
args
.
tree
and
args
.
inherit
:
err
=
"Option --inherit can be only used with --tree"
if
err
:
view
.
notify
(
event
=
"minor"
,
msg
=
self
.
parser
.
format_help
())
view
.
notify
(
event
=
"error"
,
msg
=
err
)
sys
.
exit
(
exit_codes
.
AVOCADO_FAIL
)
try
:
mux_tree
=
multiplexer
.
yaml2tree
(
args
.
multiplex_files
,
args
.
filter_only
,
args
.
filter_out
,
...
...
@@ -82,11 +103,20 @@ class Multiplexer(plugin.Plugin):
view
.
notify
(
event
=
'error'
,
msg
=
details
.
strerror
)
sys
.
exit
(
exit_codes
.
AVOCADO_JOB_FAIL
)
mux_tree
.
merge
(
args
.
default_multiplex_tree
)
if
args
.
system_wide
:
mux_tree
.
merge
(
args
.
default_multiplex_tree
)
mux_tree
.
merge
(
self
.
_from_args_tree
)
if
args
.
tree
:
view
.
notify
(
event
=
'message'
,
msg
=
'Config file tree structure:'
)
view
.
notify
(
event
=
'minor'
,
msg
=
mux_tree
.
get_ascii
(
attributes
=
args
.
attr
))
if
args
.
contents
:
verbose
=
1
else
:
verbose
=
0
if
args
.
inherit
:
verbose
+=
2
use_utf8
=
settings
.
get_value
(
"runner.output"
,
"utf8"
,
key_type
=
bool
,
default
=
None
)
view
.
notify
(
event
=
'minor'
,
msg
=
tree
.
tree_view
(
mux_tree
,
verbose
,
use_utf8
))
sys
.
exit
(
exit_codes
.
AVOCADO_ALL_OK
)
variants
=
multiplexer
.
MuxTree
(
mux_tree
)
...
...
@@ -105,10 +135,15 @@ class Multiplexer(plugin.Plugin):
view
.
notify
(
event
=
'minor'
,
msg
=
'%sVariant %s: %s'
%
((
'
\n
'
if
args
.
contents
else
''
),
index
+
1
,
paths
))
if
args
.
contents
:
env
=
{}
env
=
set
()
for
node
in
tpl
:
env
.
update
(
node
.
environment
)
for
k
in
sorted
(
env
.
keys
()):
view
.
notify
(
event
=
'minor'
,
msg
=
' %s: %s'
%
(
k
,
env
[
k
]))
for
key
,
value
in
node
.
environment
.
iteritems
():
origin
=
node
.
environment_origin
[
key
].
path
env
.
add
((
"%s:%s"
%
(
origin
,
key
),
str
(
value
)))
if
not
env
:
continue
fmt
=
' %%-%ds => %%s'
%
max
([
len
(
_
[
0
])
for
_
in
env
])
for
record
in
sorted
(
env
):
view
.
notify
(
event
=
'minor'
,
msg
=
fmt
%
record
)
sys
.
exit
(
exit_codes
.
AVOCADO_ALL_OK
)
avocado/core/plugins/runner.py
浏览文件 @
361948f3
...
...
@@ -126,7 +126,9 @@ class TestRunner(plugin.Plugin):
help
=
'Filter out path(s) from multiplexing'
)
mux
.
add_argument
(
'--mux-entry'
,
nargs
=
'*'
,
default
=
None
,
help
=
"Multiplex entry point(s)"
)
mux
.
add_argument
(
'--env'
,
default
=
[],
nargs
=
'*'
)
mux
.
add_argument
(
'--env'
,
default
=
[],
nargs
=
'*'
,
help
=
"Inject [path:]key:node values into the "
"final multiplex tree."
)
super
(
TestRunner
,
self
).
configure
(
self
.
parser
)
# Export the test runner parser back to the main parser
parser
.
runner
=
self
.
parser
...
...
avocado/core/tree.py
浏览文件 @
361948f3
...
...
@@ -35,6 +35,7 @@ original base tree code and re-license under GPLv2+, given that GPLv3 and GPLv2
import
collections
import
itertools
import
locale
import
os
import
re
...
...
@@ -209,6 +210,8 @@ class TreeNode(object):
def
get_path
(
self
,
sep
=
'/'
):
""" Get node path """
if
not
self
.
parent
:
return
sep
+
str
(
self
.
name
)
path
=
[
str
(
self
.
name
)]
for
node
in
self
.
iter_parents
():
path
.
append
(
str
(
node
.
name
))
...
...
@@ -293,72 +296,6 @@ class TreeNode(object):
""" Get list of leaf nodes """
return
list
(
self
.
iter_leaves
())
def
get_ascii
(
self
,
show_internal
=
True
,
compact
=
False
,
attributes
=
None
):
"""
Get ascii-art tree structure
:param show_internal: Show intermediary nodes
:param compact: Compress the tree vertically
:param attributes: List of node attributes to be printed out ['name']
:return: string
"""
(
lines
,
_
)
=
self
.
ascii_art
(
show_internal
=
show_internal
,
compact
=
compact
,
attributes
=
attributes
)
return
'
\n
'
+
'
\n
'
.
join
(
lines
)
def
ascii_art
(
self
,
char1
=
'-'
,
show_internal
=
True
,
compact
=
False
,
attributes
=
None
):
"""
Generate ascii-art for this node
:param char1: Incomming path character [-]
:param show_internal: Show intermediary nodes
:param compact: Compress the tree vertically
:param attributes: List of node attributes to be printed out ['name']
:return: list of strings
"""
if
not
attributes
:
attributes
=
[
"name"
]
node_name
=
', '
.
join
(
map
(
str
,
[
getattr
(
self
,
v
)
for
v
in
attributes
if
hasattr
(
self
,
v
)]))
if
self
.
multiplex
:
node_name
+=
"-<>"
length
=
max
(
2
,
(
len
(
node_name
)
+
1
)
if
not
self
.
children
or
show_internal
else
3
)
pad
=
' '
*
length
_pad
=
' '
*
(
length
-
1
)
if
not
self
.
is_leaf
:
mids
=
[]
result
=
[]
for
char
in
self
.
children
:
if
len
(
self
.
children
)
==
1
:
char2
=
'-'
elif
char
is
self
.
children
[
0
]:
char2
=
'/'
elif
char
is
self
.
children
[
-
1
]:
char2
=
'
\\
'
else
:
char2
=
'-'
(
clines
,
mid
)
=
char
.
ascii_art
(
char2
,
show_internal
,
compact
,
attributes
)
mids
.
append
(
mid
+
len
(
result
))
result
.
extend
(
clines
)
if
not
compact
:
result
.
append
(
''
)
if
not
compact
:
result
.
pop
()
(
low
,
high
,
end
)
=
(
mids
[
0
],
mids
[
-
1
],
len
(
result
))
prefixes
=
([
pad
]
*
(
low
+
1
)
+
[
_pad
+
'|'
]
*
(
high
-
low
-
1
)
+
[
pad
]
*
(
end
-
high
))
mid
=
(
low
+
high
)
/
2
prefixes
[
mid
]
=
char1
+
'-'
*
(
length
-
2
)
+
prefixes
[
mid
][
-
1
]
result
=
[
p
+
l
for
(
p
,
l
)
in
zip
(
prefixes
,
result
)]
if
show_internal
:
stem
=
result
[
mid
]
result
[
mid
]
=
stem
[
0
]
+
node_name
+
stem
[
len
(
node_name
)
+
1
:]
return
result
,
mid
else
:
return
[
char1
+
'-'
+
node_name
],
0
def
detach
(
self
):
""" Detach this node from parent """
if
self
.
parent
:
...
...
@@ -540,6 +477,8 @@ def path_parent(path):
:return: the parent path as string.
"""
parent
=
path
.
rpartition
(
'/'
)[
0
]
if
not
parent
:
return
'/'
return
parent
...
...
@@ -719,3 +658,114 @@ def get_named_tree_cls(path):
children
,
path
.
split
(
':'
,
1
)[
-
1
])
return
NamedTreeNodeDebug
def
tree_view
(
root
,
verbose
=
None
,
use_utf8
=
None
):
"""
Generate tree-view of the given node
:param root: root node
:param verbose: verbosity (0, 1, 2, 3)
:param use_utf8: Use utf-8 encoding (None=autodetect)
:return: string representing this node's tree structure
"""
def
prefixed_write
(
prefix1
,
prefix2
,
value
):
"""
Split value's lines and prepend empty prefix to 2nd+ lines
:return: list of lines
"""
value
=
str
(
value
)
if
'
\n
'
not
in
value
:
return
[
prefix1
+
prefix2
+
value
]
value
=
value
.
splitlines
()
empty_prefix2
=
' '
*
len
(
prefix2
)
return
[
prefix1
+
prefix2
+
value
[
0
]]
+
[
prefix1
+
empty_prefix2
+
_
for
_
in
value
[
1
:]]
def
process_node
(
node
):
"""
Generate this node's tree-view
:return: list of lines
"""
if
node
.
multiplex
:
down
=
charset
[
'DoubleDown'
]
down_right
=
charset
[
'DoubleDownRight'
]
right
=
charset
[
'DoubleRight'
]
else
:
down
=
charset
[
'Down'
]
down_right
=
charset
[
'DownRight'
]
right
=
charset
[
'Right'
]
out
=
[
node
.
name
]
if
verbose
>=
2
and
node
.
is_leaf
:
values
=
node
.
environment
.
iteritems
()
elif
verbose
in
(
1
,
3
):
values
=
node
.
value
.
iteritems
()
else
:
values
=
None
if
values
:
val
=
charset
[
'Value'
]
if
node
.
children
:
val_prefix
=
down
else
:
val_prefix
=
' '
for
key
,
value
in
values
:
out
.
extend
(
prefixed_write
(
val_prefix
,
val
+
key
+
': '
,
value
))
if
node
.
children
:
for
child
in
node
.
children
[:
-
1
]:
lines
=
process_node
(
child
)
out
.
append
(
down_right
+
lines
[
0
])
out
.
extend
(
down
+
line
for
line
in
lines
[
1
:])
lines
=
process_node
(
node
.
children
[
-
1
])
out
.
append
(
right
+
lines
[
0
])
empty_down_right
=
' '
*
len
(
down_right
)
out
.
extend
(
empty_down_right
+
line
for
line
in
lines
[
1
:])
return
out
if
use_utf8
is
None
:
use_utf8
=
locale
.
getdefaultlocale
()[
1
]
==
'UTF-8'
if
use_utf8
:
charset
=
{
'DoubleDown'
:
u
'
\u2551
'
,
'DoubleDownRight'
:
u
'
\u2560\u2550\u2550
'
,
'DoubleRight'
:
u
'
\u255a\u2550\u2550
'
,
'Down'
:
u
'
\u2503
'
,
'DownRight'
:
u
'
\u2523\u2501\u2501
'
,
'Right'
:
u
'
\u2517\u2501\u2501
'
,
'Value'
:
u
'
\u2192
'
}
else
:
# ASCII fallback
charset
=
{
'Down'
:
' | '
,
'DownRight'
:
' |-- '
,
'Right'
:
'
\\
-- '
,
'DoubleDown'
:
' # '
,
'DoubleDownRight'
:
' #== '
,
'DoubleRight'
:
' #== '
,
'Value'
:
' -> '
}
if
root
.
multiplex
:
down
=
charset
[
'DoubleDown'
]
down_right
=
charset
[
'DoubleDownRight'
]
right
=
charset
[
'DoubleRight'
]
else
:
down
=
charset
[
'Down'
]
down_right
=
charset
[
'DownRight'
]
right
=
charset
[
'Right'
]
out
=
[]
if
(
verbose
>=
2
)
and
root
.
is_leaf
:
values
=
root
.
environment
.
iteritems
()
elif
verbose
in
(
1
,
3
):
values
=
root
.
value
.
iteritems
()
else
:
values
=
None
if
values
:
prefix
=
charset
[
'Value'
].
lstrip
()
for
key
,
value
in
values
:
out
.
extend
(
prefixed_write
(
prefix
,
key
+
': '
,
value
))
if
root
.
children
:
for
child
in
root
.
children
[:
-
1
]:
lines
=
process_node
(
child
)
out
.
append
(
down_right
+
lines
[
0
])
out
.
extend
(
down
+
line
for
line
in
lines
[
1
:])
lines
=
process_node
(
root
.
children
[
-
1
])
out
.
append
(
right
+
lines
[
0
])
out
.
extend
(
' '
*
len
(
down_right
)
+
line
for
line
in
lines
[
1
:])
# When not on TTY we need to force the encoding
return
'
\n
'
.
join
(
out
).
encode
(
'utf-8'
if
use_utf8
else
'ascii'
)
etc/avocado/avocado.conf
浏览文件 @
361948f3
...
...
@@ -27,6 +27,8 @@ profilers = /etc/avocado/sysinfo/profilers
[
runner
.
output
]
# Whether to display colored output in terminals that support it
colored
=
True
# Use utf8 encoding (True, False, None=autodetect)
utf8
=
[
runner
.
behavior
]
# Keep job temporary files after jobs (useful for avocado debugging)
...
...
selftests/all/functional/avocado/multiplex_tests.py
浏览文件 @
361948f3
...
...
@@ -20,12 +20,13 @@ if os.path.isdir(os.path.join(basedir, 'avocado')):
from
avocado.utils
import
process
DEBUG_OUT
=
"""Variant 16: amd@examples/mux-environment.yaml, virtio@examples/mux-environment.yaml, mint@examples/mux-environment.yaml, debug@examples/mux-environment.yaml
corruptlist: nonlist@examples/mux-selftest.yaml:/hw/disk
cpu_CFLAGS: -march=athlon64@examples/mux-environment.yaml:/hw/cpu/amd
disk_type: virtio@examples/mux-environment.yaml:/hw/disk/virtio
init: systemv@examples/mux-environment.yaml:/distro/mint
joinlist: ['first_item']@examples/mux-selftest.yaml:/hw/cpu + ['second', 'third']@examples/mux-selftest.yaml:/hw/cpu/amd
opt_CFLAGS: -O0 -g@examples/mux-environment.yaml:/env/debug
/distro/mint:init => systemv@examples/mux-environment.yaml:/distro/mint
/env/debug:opt_CFLAGS => -O0 -g@examples/mux-environment.yaml:/env/debug
/hw/cpu/amd:cpu_CFLAGS => -march=athlon64@examples/mux-environment.yaml:/hw/cpu/amd
/hw/cpu/amd:joinlist => ['first_item']@examples/mux-selftest.yaml:/hw/cpu + ['second', 'third']@examples/mux-selftest.yaml:/hw/cpu/amd
/hw/disk/virtio:disk_type => virtio@examples/mux-environment.yaml:/hw/disk/virtio
/hw/disk:corruptlist => nonlist@examples/mux-selftest.yaml:/hw/disk
/hw:corruptlist => ['upper_node_list']@examples/mux-selftest.yaml:/hw
"""
...
...
selftests/all/unit/avocado/tree_unittest.py
浏览文件 @
361948f3
...
...
@@ -8,10 +8,16 @@ else:
from
avocado.core
import
tree
if
__name__
==
"__main__"
:
PATH_PREFIX
=
"../../../../"
else
:
PATH_PREFIX
=
""
class
TestTree
(
unittest
.
TestCase
):
# Share tree with all tests
tree
=
tree
.
create_from_yaml
([
'/:examples/mux-selftest.yaml'
])
tree
=
tree
.
create_from_yaml
([
'/:'
+
PATH_PREFIX
+
'examples/mux-selftest.yaml'
])
def
test_node_order
(
self
):
self
.
assertIsInstance
(
self
.
tree
,
tree
.
TreeNode
)
...
...
@@ -112,7 +118,7 @@ class TestTree(unittest.TestCase):
'prod'
]
self
.
assertEqual
(
leaves
,
self
.
tree
.
get_leaves
())
# asci contain all leaves and doesn't raise any exceptions
ascii
=
self
.
tree
.
get_ascii
(
)
ascii
=
tree
.
tree_view
(
self
.
tree
,
0
,
False
)
for
leaf
in
leaves
:
self
.
assertIn
(
leaf
,
ascii
,
"Leaf %s not in asci:
\n
%s"
%
(
leaf
,
ascii
))
...
...
@@ -154,8 +160,8 @@ class TestTree(unittest.TestCase):
tree2
.
children
[
0
].
children
[
2
].
children
[
1
].
value
)
def
test_advanced_yaml
(
self
):
tree2
=
tree
.
create_from_yaml
([
'/:
examples/mux-selftest-advanced.
'
'yaml'
])
tree2
=
tree
.
create_from_yaml
([
'/:
'
+
PATH_PREFIX
+
'examples/mux-
'
'
selftest-advanced.
yaml'
])
exp
=
[
'intel'
,
'amd'
,
'arm'
,
'scsi'
,
'virtio'
,
'fedora'
,
'6'
,
'7'
,
'gentoo'
,
'mint'
,
'prod'
,
'new_node'
]
act
=
tree2
.
get_leaves
()
...
...
@@ -190,10 +196,10 @@ class TestTree(unittest.TestCase):
class
TestPathParent
(
unittest
.
TestCase
):
def
test_empty_string
(
self
):
self
.
assertEqual
(
tree
.
path_parent
(
''
),
''
)
self
.
assertEqual
(
tree
.
path_parent
(
''
),
'
/
'
)
def
test_on_root
(
self
):
self
.
assertEqual
(
tree
.
path_parent
(
'/'
),
''
)
self
.
assertEqual
(
tree
.
path_parent
(
'/'
),
'
/
'
)
def
test_direct_parent
(
self
):
self
.
assertEqual
(
tree
.
path_parent
(
'/os/linux'
),
'/os'
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录