Compare commits
3 Commits
ab5d6b7181
...
556c29fd4b
Author | SHA1 | Date |
---|---|---|
Síle Ekaterin Liszka | 556c29fd4b | |
Síle Ekaterin Liszka | 9e735ab7b8 | |
Síle Ekaterin Liszka | bd6887db0e |
|
@ -34,3 +34,9 @@ Issues = 'https://gitea.treehouse.systems/VulpineAmethyst/py-xbc/issues'
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["setuptools>=61.0"]
|
requires = ["setuptools>=61.0"]
|
||||||
build-backend = "setuptools.build_meta"
|
build-backend = "setuptools.build_meta"
|
||||||
|
|
||||||
|
[tool.pytest.ini_options]
|
||||||
|
addopts = [
|
||||||
|
"--import-mode=importlib",
|
||||||
|
]
|
||||||
|
pythonpath = 'src'
|
|
@ -164,6 +164,15 @@ def unquote(val):
|
||||||
return val[1:-1]
|
return val[1:-1]
|
||||||
return val.strip()
|
return val.strip()
|
||||||
|
|
||||||
|
def key_walk(d, key):
|
||||||
|
split = key.split('.')
|
||||||
|
|
||||||
|
for i in range(len(split) - 1, 0, -1):
|
||||||
|
x = '.'.join(split[:i])
|
||||||
|
print(x)
|
||||||
|
if x not in d:
|
||||||
|
d[x] = False
|
||||||
|
|
||||||
def parse_block(key, seq):
|
def parse_block(key, seq):
|
||||||
if isinstance(seq, list) and len(seq) == 1 and isinstance(seq[0], list):
|
if isinstance(seq, list) and len(seq) == 1 and isinstance(seq[0], list):
|
||||||
seq = seq[0]
|
seq = seq[0]
|
||||||
|
@ -215,6 +224,9 @@ def parse_block(key, seq):
|
||||||
assign = assign[0]
|
assign = assign[0]
|
||||||
|
|
||||||
ret[k] = assign
|
ret[k] = assign
|
||||||
|
|
||||||
|
if '.' in k:
|
||||||
|
key_walk(ret, k)
|
||||||
elif isinstance(item, Block):
|
elif isinstance(item, Block):
|
||||||
value = item.contents
|
value = item.contents
|
||||||
|
|
||||||
|
@ -224,7 +236,12 @@ def parse_block(key, seq):
|
||||||
if not isinstance(value, list):
|
if not isinstance(value, list):
|
||||||
value = [value]
|
value = [value]
|
||||||
|
|
||||||
ret.update(parse_block(k, value))
|
d = parse_block(k, value)
|
||||||
|
|
||||||
|
for k, v in d.items():
|
||||||
|
if k in ret:
|
||||||
|
continue
|
||||||
|
ret[k] = v
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
foo {
|
|
||||||
bar = 1
|
|
||||||
foo = 2
|
|
||||||
}
|
|
||||||
foo = 4
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from xbc import loads_xbc, ParseError
|
||||||
|
|
||||||
|
|
||||||
|
def test_key():
|
||||||
|
assert loads_xbc('a') == {'a': True}
|
||||||
|
|
||||||
|
def test_dot_key():
|
||||||
|
assert loads_xbc('a.a') == {'a.a': True}
|
||||||
|
|
||||||
|
def test_key_eq():
|
||||||
|
assert loads_xbc('a =') == {'a': True}
|
||||||
|
|
||||||
|
def test_keyvalue():
|
||||||
|
assert loads_xbc('a = 1') == {'a': '1'}
|
||||||
|
|
||||||
|
def test_keyvalue_space():
|
||||||
|
assert loads_xbc('a = a b') == {'a': 'a b'}
|
||||||
|
|
||||||
|
def test_dot_keyvalue():
|
||||||
|
assert loads_xbc('a.a = 1') == {'a': False, 'a.a': '1'}
|
||||||
|
|
||||||
|
def test_keys():
|
||||||
|
assert loads_xbc('a;b') == {'a': True, 'b': True}
|
||||||
|
|
||||||
|
def test_dot_keys():
|
||||||
|
assert loads_xbc('a.a;a.b') == {'a.a': True, 'a.b': True}
|
||||||
|
|
||||||
|
def test_quoted():
|
||||||
|
assert loads_xbc('a = "b"') == {'a': 'b'}
|
||||||
|
|
||||||
|
def test_quoted_space():
|
||||||
|
assert loads_xbc('a = "b "') == {'a': 'b '}
|
||||||
|
|
||||||
|
def test_array():
|
||||||
|
assert loads_xbc('a = 1, 2') == {'a': ['1', '2']}
|
||||||
|
|
||||||
|
def test_reassignment():
|
||||||
|
with pytest.raises(ParseError):
|
||||||
|
loads_xbc('a = 1\na = 2')
|
||||||
|
|
||||||
|
def test_reassignment_colon():
|
||||||
|
with pytest.raises(ParseError):
|
||||||
|
loads_xbc('a = 1;a = 2')
|
||||||
|
|
||||||
|
def test_ovewrite_nonexistent():
|
||||||
|
with pytest.raises(ParseError):
|
||||||
|
loads_xbc('a := 1')
|
|
@ -1,62 +0,0 @@
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
from xbc import loads_xbc, ParseError
|
|
||||||
|
|
||||||
class TestBareLoad:
|
|
||||||
def test_key(self):
|
|
||||||
assert loads_xbc('a') == {'a': True}
|
|
||||||
|
|
||||||
def test_dot_key(self):
|
|
||||||
assert loads_xbc('a.a') == {'a.a': True}
|
|
||||||
|
|
||||||
def test_key_eq(self):
|
|
||||||
assert loads_xbc('a =') == {'a': True}
|
|
||||||
|
|
||||||
def test_keyvalue(self):
|
|
||||||
assert loads_xbc('a = 1') == {'a': '1'}
|
|
||||||
|
|
||||||
def test_dot_keyvalue(self):
|
|
||||||
assert loads_xbc('a.a = 1') == {'a.a': '1'}
|
|
||||||
|
|
||||||
def test_keys(self):
|
|
||||||
assert loads_xbc('a;b') == {'a': True, 'b': True}
|
|
||||||
|
|
||||||
def test_dot_keys(self):
|
|
||||||
assert loads_xbc('a.a;a.b') == {'a.a': True, 'a.b': True}
|
|
||||||
|
|
||||||
def test_string(self):
|
|
||||||
assert loads_xbc('a = "b"') == {'a': 'b'}
|
|
||||||
|
|
||||||
def test_array(self):
|
|
||||||
assert loads_xbc('a = 1, 2') == {'a': ['1', '2']}
|
|
||||||
|
|
||||||
def test_reassignment(self):
|
|
||||||
with pytest.raises(ParseError):
|
|
||||||
loads_xbc('a = 1\na = 2')
|
|
||||||
|
|
||||||
def test_reassignment_colon(self):
|
|
||||||
with pytest.raises(ParseError):
|
|
||||||
loads_xbc('a = 1;a = 2')
|
|
||||||
|
|
||||||
def test_ovewrite_nonexistent(self):
|
|
||||||
with pytest.raises(ParseError):
|
|
||||||
loads_xbc('a := 1')
|
|
||||||
|
|
||||||
class TestBlockLoad:
|
|
||||||
def test_keyvalue(self):
|
|
||||||
assert loads_xbc('a { a = 1 }') == {'a': False, 'a.a': '1'}
|
|
||||||
|
|
||||||
def test_nested_block(self):
|
|
||||||
assert loads_xbc('a { b { c = 1 } }') == {'a.b.c': '1', 'a': False, 'a.b': False}
|
|
||||||
|
|
||||||
def test_keyvalue_and_block(self):
|
|
||||||
assert loads_xbc('a = 1\na { a = 1 }') == {'a': '1', 'a.a': '1'}
|
|
||||||
|
|
||||||
def test_reassign_colon(self):
|
|
||||||
with pytest.raises(ParseError):
|
|
||||||
loads_xbc('a { a = 1; a = 2 }')
|
|
||||||
|
|
||||||
def test_assign_after_block(self):
|
|
||||||
with pytest.raises(ParseError):
|
|
||||||
loads_xbc('a { a = 1 }\na = 1')
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from xbc import loads_xbc, ParseError
|
||||||
|
|
||||||
|
def test_empty():
|
||||||
|
assert loads_xbc('a {}') == {'a': True}
|
||||||
|
|
||||||
|
def test_keyvalue():
|
||||||
|
assert loads_xbc('a { a = 1 }') == {'a': False, 'a.a': '1'}
|
||||||
|
|
||||||
|
def test_nested_block():
|
||||||
|
assert loads_xbc('a { b { c = 1 } }') == {'a.b.c': '1', 'a': False, 'a.b': False}
|
||||||
|
|
||||||
|
def test_keyvalue_and_block():
|
||||||
|
assert loads_xbc('a = 1\na { a = 1 }') == {'a': False, 'a': '1', 'a.a': '1'}
|
||||||
|
|
||||||
|
def test_reassign_colon():
|
||||||
|
with pytest.raises(ParseError):
|
||||||
|
loads_xbc('a { a = 1; a = 2 }')
|
||||||
|
|
||||||
|
def test_assign_after_block():
|
||||||
|
with pytest.raises(ParseError):
|
||||||
|
loads_xbc('a { a = 1 }\na = 1')
|
|
@ -0,0 +1,86 @@
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from xbc import load_xbc
|
||||||
|
|
||||||
|
def test_01():
|
||||||
|
d = {
|
||||||
|
'feature.option': False,
|
||||||
|
'feature': False,
|
||||||
|
'feature.option.foo': '1',
|
||||||
|
'feature.option.bar': '2'
|
||||||
|
}
|
||||||
|
assert load_xbc('tests/01-keyvalue.xbc') == d
|
||||||
|
|
||||||
|
def test_02():
|
||||||
|
d = {
|
||||||
|
'feature.option': False,
|
||||||
|
'feature': False,
|
||||||
|
'feature.option.foo': '1',
|
||||||
|
'feature.option.bar': '2'
|
||||||
|
}
|
||||||
|
assert load_xbc('tests/02-block-keyvalue.xbc') == d
|
||||||
|
|
||||||
|
def test_03():
|
||||||
|
d = {
|
||||||
|
'feature': False,
|
||||||
|
'feature.options': ['foo', 'bar']
|
||||||
|
}
|
||||||
|
assert load_xbc('tests/03-keyvalue-string.xbc') == d
|
||||||
|
|
||||||
|
def test_10():
|
||||||
|
d = {
|
||||||
|
'feature.option': False,
|
||||||
|
'feature': False,
|
||||||
|
'feature.option.foo': '1',
|
||||||
|
'feature.option.bar': '2'
|
||||||
|
}
|
||||||
|
assert load_xbc('tests/10-compact.xbc') == d
|
||||||
|
|
||||||
|
def test_11():
|
||||||
|
d = {
|
||||||
|
'ftrace': False,
|
||||||
|
'ftrace.event': False,
|
||||||
|
'ftrace.event.task': False,
|
||||||
|
'ftrace.event.task.task_newtask': False,
|
||||||
|
'ftrace.event.task.task_newtask.filter': "pid < 128",
|
||||||
|
'ftrace.event.task.task_newtask.enable': True,
|
||||||
|
'ftrace.event.kprobes': False,
|
||||||
|
'ftrace.event.kprobes.vfs_read': False,
|
||||||
|
'ftrace.event.kprobes.vfs_read.probes': "vfs_read $arg1 $arg2",
|
||||||
|
'ftrace.event.kprobes.vfs_read.filter': "common_pid < 200",
|
||||||
|
'ftrace.event.kprobes.vfs_read.enable': True,
|
||||||
|
'ftrace.event.synthetic': False,
|
||||||
|
'ftrace.event.synthetic.initcall_latency': False,
|
||||||
|
'ftrace.event.synthetic.initcall_latency.fields': ["unsigned long func", "u64 lat"],
|
||||||
|
'ftrace.event.synthetic.initcall_latency.actions': "hist:keys=func.sym,lat:vals=lat:sort=lat",
|
||||||
|
'ftrace.event.initcall': False,
|
||||||
|
'ftrace.event.initcall.initcall_start': False,
|
||||||
|
'ftrace.event.initcall.initcall_start.actions': "hist:keys=func:ts0=common_timestamp.usecs",
|
||||||
|
'ftrace.event.initcall.initcall_finish': False,
|
||||||
|
'ftrace.event.initcall.initcall_finish.actions': "hist:keys=func:lat=common_timestamp.usecs-$ts0:onmatch(initcall.initcall_start).initcall_latency(func,$lat)"
|
||||||
|
}
|
||||||
|
assert load_xbc('tests/11-config.xbc') == d
|
||||||
|
|
||||||
|
def test_12():
|
||||||
|
d = {
|
||||||
|
'ftrace': False,
|
||||||
|
'ftrace.event': False,
|
||||||
|
'ftrace.event.synthetic': False,
|
||||||
|
'ftrace.event.synthetic.initcall_latency': False,
|
||||||
|
'ftrace.event.synthetic.initcall_latency.fields': ["unsigned long func", "u64 lat"],
|
||||||
|
'ftrace.event.synthetic.initcall_latency.hist': False,
|
||||||
|
'ftrace.event.synthetic.initcall_latency.hist.from': False,
|
||||||
|
'ftrace.event.synthetic.initcall_latency.hist.from.event': 'initcall.initcall_start',
|
||||||
|
'ftrace.event.synthetic.initcall_latency.hist.from.key': 'func',
|
||||||
|
'ftrace.event.synthetic.initcall_latency.hist.from.assigns': "ts0=common_timestamp.usecs",
|
||||||
|
'ftrace.event.synthetic.initcall_latency.hist.to': False,
|
||||||
|
'ftrace.event.synthetic.initcall_latency.hist.to.event': 'initcall.initcall_finish',
|
||||||
|
'ftrace.event.synthetic.initcall_latency.hist.to.key': 'func',
|
||||||
|
'ftrace.event.synthetic.initcall_latency.hist.to.assigns': "lat=common_timestamp.usecs-$ts0",
|
||||||
|
'ftrace.event.synthetic.initcall_latency.hist.to.onmatch': ['func', '$lat'],
|
||||||
|
'ftrace.event.synthetic.initcall_latency.hist.keys': ['func.sym', 'lat'],
|
||||||
|
'ftrace.event.synthetic.initcall_latency.hist.vals': 'lat',
|
||||||
|
'ftrace.event.synthetic.initcall_latency.hist.sort': 'lat'
|
||||||
|
}
|
||||||
|
assert load_xbc('tests/12-config2.xbc') == d
|
|
@ -0,0 +1,33 @@
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from pyparsing.exceptions import ParseException
|
||||||
|
from xbc import loads_xbc, ParseError
|
||||||
|
|
||||||
|
# this should fail but does not.
|
||||||
|
@pytest.mark.xfail
|
||||||
|
def test_whitespace_vc():
|
||||||
|
with pytest.raises(ParseError):
|
||||||
|
loads_xbc('x = a\n, b')
|
||||||
|
|
||||||
|
# this should fail but does not.
|
||||||
|
@pytest.mark.xfail
|
||||||
|
def test_extra_quote():
|
||||||
|
with pytest.raises(ParseException):
|
||||||
|
loads_xbc("x = '''")
|
||||||
|
|
||||||
|
def test_lone_plus():
|
||||||
|
with pytest.raises(ParseException):
|
||||||
|
loads_xbc('+')
|
||||||
|
|
||||||
|
def test_lone_rbrace():
|
||||||
|
with pytest.raises(ParseException):
|
||||||
|
loads_xbc('}')
|
||||||
|
|
||||||
|
def test_lone_lbrace():
|
||||||
|
with pytest.raises(ParseException):
|
||||||
|
loads_xbc('{')
|
||||||
|
|
||||||
|
def test_lone_braces():
|
||||||
|
with pytest.raises(ParseException):
|
||||||
|
loads_xbc('{}')
|
Loading…
Reference in New Issue