mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
This switched `codegen` from the `autopep8` formatting to the `black` one, and applies it to `bulk_mad_generator.py` as well. We can enroll more python scripts to it in the future.
780 lines
23 KiB
Python
780 lines
23 KiB
Python
import collections
|
|
import sys
|
|
|
|
from misc.codegen.generators import dbschemegen
|
|
from misc.codegen.lib import dbscheme
|
|
from misc.codegen.test.utils import *
|
|
|
|
InputExpectedPair = collections.namedtuple("InputExpectedPair", ("input", "expected"))
|
|
|
|
|
|
@pytest.fixture(
|
|
params=[
|
|
InputExpectedPair(None, None),
|
|
InputExpectedPair("foodir", pathlib.Path("foodir")),
|
|
]
|
|
)
|
|
def dir_param(request):
|
|
return request.param
|
|
|
|
|
|
@pytest.fixture
|
|
def generate(opts, input, renderer):
|
|
def func(classes, null=None):
|
|
input.classes = {cls.name: cls for cls in classes}
|
|
input.null = null
|
|
((out, data),) = run_generation(dbschemegen.generate, opts, renderer).items()
|
|
assert out is opts.dbscheme
|
|
return data
|
|
|
|
return func
|
|
|
|
|
|
def test_empty(generate):
|
|
assert generate([]) == dbscheme.Scheme(
|
|
src=schema_file.name,
|
|
includes=[],
|
|
declarations=[],
|
|
)
|
|
|
|
|
|
def test_includes(input, opts, generate):
|
|
includes = ["foo", "bar"]
|
|
input.includes = includes
|
|
for i in includes:
|
|
write(opts.schema.parent / i, i + " data")
|
|
|
|
assert generate([]) == dbscheme.Scheme(
|
|
src=schema_file.name,
|
|
includes=[
|
|
dbscheme.SchemeInclude(
|
|
src=pathlib.Path(i),
|
|
data=i + " data",
|
|
)
|
|
for i in includes
|
|
],
|
|
declarations=[],
|
|
)
|
|
|
|
|
|
def test_empty_final_class(generate, dir_param):
|
|
assert generate(
|
|
[
|
|
schema.Class("Object", pragmas={"group": dir_param.input}),
|
|
]
|
|
) == dbscheme.Scheme(
|
|
src=schema_file.name,
|
|
includes=[],
|
|
declarations=[
|
|
dbscheme.Table(
|
|
name="objects",
|
|
columns=[
|
|
dbscheme.Column("id", "@object", binding=True),
|
|
],
|
|
dir=dir_param.expected,
|
|
)
|
|
],
|
|
)
|
|
|
|
|
|
def test_final_class_with_single_scalar_field(generate, dir_param):
|
|
assert generate(
|
|
[
|
|
schema.Class(
|
|
"Object",
|
|
pragmas={"group": dir_param.input},
|
|
properties=[
|
|
schema.SingleProperty("foo", "bar"),
|
|
],
|
|
),
|
|
]
|
|
) == dbscheme.Scheme(
|
|
src=schema_file.name,
|
|
includes=[],
|
|
declarations=[
|
|
dbscheme.Table(
|
|
name="objects",
|
|
columns=[
|
|
dbscheme.Column("id", "@object", binding=True),
|
|
dbscheme.Column("foo", "bar"),
|
|
],
|
|
dir=dir_param.expected,
|
|
)
|
|
],
|
|
)
|
|
|
|
|
|
def test_final_class_with_single_class_field(generate, dir_param):
|
|
assert generate(
|
|
[
|
|
schema.Class(
|
|
"Object",
|
|
pragmas={"group": dir_param.input},
|
|
properties=[
|
|
schema.SingleProperty("foo", "Bar"),
|
|
],
|
|
),
|
|
]
|
|
) == dbscheme.Scheme(
|
|
src=schema_file.name,
|
|
includes=[],
|
|
declarations=[
|
|
dbscheme.Table(
|
|
name="objects",
|
|
columns=[
|
|
dbscheme.Column("id", "@object", binding=True),
|
|
dbscheme.Column("foo", "@bar"),
|
|
],
|
|
dir=dir_param.expected,
|
|
)
|
|
],
|
|
)
|
|
|
|
|
|
def test_final_class_with_optional_field(generate, dir_param):
|
|
assert generate(
|
|
[
|
|
schema.Class(
|
|
"Object",
|
|
pragmas={"group": dir_param.input},
|
|
properties=[
|
|
schema.OptionalProperty("foo", "bar"),
|
|
],
|
|
),
|
|
]
|
|
) == dbscheme.Scheme(
|
|
src=schema_file.name,
|
|
includes=[],
|
|
declarations=[
|
|
dbscheme.Table(
|
|
name="objects",
|
|
columns=[
|
|
dbscheme.Column("id", "@object", binding=True),
|
|
],
|
|
dir=dir_param.expected,
|
|
),
|
|
dbscheme.Table(
|
|
name="object_foos",
|
|
keyset=dbscheme.KeySet(["id"]),
|
|
columns=[
|
|
dbscheme.Column("id", "@object"),
|
|
dbscheme.Column("foo", "bar"),
|
|
],
|
|
dir=dir_param.expected,
|
|
),
|
|
],
|
|
)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"property_cls", [schema.RepeatedProperty, schema.RepeatedOptionalProperty]
|
|
)
|
|
def test_final_class_with_repeated_field(generate, property_cls, dir_param):
|
|
assert generate(
|
|
[
|
|
schema.Class(
|
|
"Object",
|
|
pragmas={"group": dir_param.input},
|
|
properties=[
|
|
property_cls("foo", "bar"),
|
|
],
|
|
),
|
|
]
|
|
) == dbscheme.Scheme(
|
|
src=schema_file.name,
|
|
includes=[],
|
|
declarations=[
|
|
dbscheme.Table(
|
|
name="objects",
|
|
columns=[
|
|
dbscheme.Column("id", "@object", binding=True),
|
|
],
|
|
dir=dir_param.expected,
|
|
),
|
|
dbscheme.Table(
|
|
name="object_foos",
|
|
keyset=dbscheme.KeySet(["id", "index"]),
|
|
columns=[
|
|
dbscheme.Column("id", "@object"),
|
|
dbscheme.Column("index", "int"),
|
|
dbscheme.Column("foo", "bar"),
|
|
],
|
|
dir=dir_param.expected,
|
|
),
|
|
],
|
|
)
|
|
|
|
|
|
def test_final_class_with_repeated_unordered_field(generate, dir_param):
|
|
assert generate(
|
|
[
|
|
schema.Class(
|
|
"Object",
|
|
pragmas={"group": dir_param.input},
|
|
properties=[
|
|
schema.RepeatedUnorderedProperty("foo", "bar"),
|
|
],
|
|
),
|
|
]
|
|
) == dbscheme.Scheme(
|
|
src=schema_file.name,
|
|
includes=[],
|
|
declarations=[
|
|
dbscheme.Table(
|
|
name="objects",
|
|
columns=[
|
|
dbscheme.Column("id", "@object", binding=True),
|
|
],
|
|
dir=dir_param.expected,
|
|
),
|
|
dbscheme.Table(
|
|
name="object_foos",
|
|
columns=[
|
|
dbscheme.Column("id", "@object"),
|
|
dbscheme.Column("foo", "bar"),
|
|
],
|
|
dir=dir_param.expected,
|
|
),
|
|
],
|
|
)
|
|
|
|
|
|
def test_final_class_with_predicate_field(generate, dir_param):
|
|
assert generate(
|
|
[
|
|
schema.Class(
|
|
"Object",
|
|
pragmas={"group": dir_param.input},
|
|
properties=[
|
|
schema.PredicateProperty("foo"),
|
|
],
|
|
),
|
|
]
|
|
) == dbscheme.Scheme(
|
|
src=schema_file.name,
|
|
includes=[],
|
|
declarations=[
|
|
dbscheme.Table(
|
|
name="objects",
|
|
columns=[
|
|
dbscheme.Column("id", "@object", binding=True),
|
|
],
|
|
dir=dir_param.expected,
|
|
),
|
|
dbscheme.Table(
|
|
name="object_foo",
|
|
keyset=dbscheme.KeySet(["id"]),
|
|
columns=[
|
|
dbscheme.Column("id", "@object"),
|
|
],
|
|
dir=dir_param.expected,
|
|
),
|
|
],
|
|
)
|
|
|
|
|
|
def test_final_class_with_more_fields(generate, dir_param):
|
|
assert generate(
|
|
[
|
|
schema.Class(
|
|
"Object",
|
|
pragmas={"group": dir_param.input},
|
|
properties=[
|
|
schema.SingleProperty("one", "x"),
|
|
schema.SingleProperty("two", "y"),
|
|
schema.OptionalProperty("three", "z"),
|
|
schema.RepeatedProperty("four", "u"),
|
|
schema.RepeatedOptionalProperty("five", "v"),
|
|
schema.PredicateProperty("six"),
|
|
],
|
|
),
|
|
]
|
|
) == dbscheme.Scheme(
|
|
src=schema_file.name,
|
|
includes=[],
|
|
declarations=[
|
|
dbscheme.Table(
|
|
name="objects",
|
|
columns=[
|
|
dbscheme.Column("id", "@object", binding=True),
|
|
dbscheme.Column("one", "x"),
|
|
dbscheme.Column("two", "y"),
|
|
],
|
|
dir=dir_param.expected,
|
|
),
|
|
dbscheme.Table(
|
|
name="object_threes",
|
|
keyset=dbscheme.KeySet(["id"]),
|
|
columns=[
|
|
dbscheme.Column("id", "@object"),
|
|
dbscheme.Column("three", "z"),
|
|
],
|
|
dir=dir_param.expected,
|
|
),
|
|
dbscheme.Table(
|
|
name="object_fours",
|
|
keyset=dbscheme.KeySet(["id", "index"]),
|
|
columns=[
|
|
dbscheme.Column("id", "@object"),
|
|
dbscheme.Column("index", "int"),
|
|
dbscheme.Column("four", "u"),
|
|
],
|
|
dir=dir_param.expected,
|
|
),
|
|
dbscheme.Table(
|
|
name="object_fives",
|
|
keyset=dbscheme.KeySet(["id", "index"]),
|
|
columns=[
|
|
dbscheme.Column("id", "@object"),
|
|
dbscheme.Column("index", "int"),
|
|
dbscheme.Column("five", "v"),
|
|
],
|
|
dir=dir_param.expected,
|
|
),
|
|
dbscheme.Table(
|
|
name="object_six",
|
|
keyset=dbscheme.KeySet(["id"]),
|
|
columns=[
|
|
dbscheme.Column("id", "@object"),
|
|
],
|
|
dir=dir_param.expected,
|
|
),
|
|
],
|
|
)
|
|
|
|
|
|
def test_empty_class_with_derived(generate):
|
|
assert generate(
|
|
[
|
|
schema.Class(name="Base", derived={"Left", "Right"}),
|
|
schema.Class(name="Left", bases=["Base"]),
|
|
schema.Class(name="Right", bases=["Base"]),
|
|
]
|
|
) == dbscheme.Scheme(
|
|
src=schema_file.name,
|
|
includes=[],
|
|
declarations=[
|
|
dbscheme.Union(
|
|
lhs="@base",
|
|
rhs=["@left", "@right"],
|
|
),
|
|
dbscheme.Table(
|
|
name="lefts",
|
|
columns=[dbscheme.Column("id", "@left", binding=True)],
|
|
),
|
|
dbscheme.Table(
|
|
name="rights",
|
|
columns=[dbscheme.Column("id", "@right", binding=True)],
|
|
),
|
|
],
|
|
)
|
|
|
|
|
|
def test_class_with_derived_and_single_property(generate, dir_param):
|
|
assert generate(
|
|
[
|
|
schema.Class(
|
|
name="Base",
|
|
derived={"Left", "Right"},
|
|
pragmas={"group": dir_param.input},
|
|
properties=[
|
|
schema.SingleProperty("single", "Prop"),
|
|
],
|
|
),
|
|
schema.Class(name="Left", bases=["Base"]),
|
|
schema.Class(name="Right", bases=["Base"]),
|
|
]
|
|
) == dbscheme.Scheme(
|
|
src=schema_file.name,
|
|
includes=[],
|
|
declarations=[
|
|
dbscheme.Union(
|
|
lhs="@base",
|
|
rhs=["@left", "@right"],
|
|
),
|
|
dbscheme.Table(
|
|
name="bases",
|
|
keyset=dbscheme.KeySet(["id"]),
|
|
columns=[
|
|
dbscheme.Column("id", "@base"),
|
|
dbscheme.Column("single", "@prop"),
|
|
],
|
|
dir=dir_param.expected,
|
|
),
|
|
dbscheme.Table(
|
|
name="lefts",
|
|
columns=[dbscheme.Column("id", "@left", binding=True)],
|
|
),
|
|
dbscheme.Table(
|
|
name="rights",
|
|
columns=[dbscheme.Column("id", "@right", binding=True)],
|
|
),
|
|
],
|
|
)
|
|
|
|
|
|
def test_class_with_derived_and_optional_property(generate, dir_param):
|
|
assert generate(
|
|
[
|
|
schema.Class(
|
|
name="Base",
|
|
derived={"Left", "Right"},
|
|
pragmas={"group": dir_param.input},
|
|
properties=[
|
|
schema.OptionalProperty("opt", "Prop"),
|
|
],
|
|
),
|
|
schema.Class(name="Left", bases=["Base"]),
|
|
schema.Class(name="Right", bases=["Base"]),
|
|
]
|
|
) == dbscheme.Scheme(
|
|
src=schema_file.name,
|
|
includes=[],
|
|
declarations=[
|
|
dbscheme.Union(
|
|
lhs="@base",
|
|
rhs=["@left", "@right"],
|
|
),
|
|
dbscheme.Table(
|
|
name="base_opts",
|
|
keyset=dbscheme.KeySet(["id"]),
|
|
columns=[
|
|
dbscheme.Column("id", "@base"),
|
|
dbscheme.Column("opt", "@prop"),
|
|
],
|
|
dir=dir_param.expected,
|
|
),
|
|
dbscheme.Table(
|
|
name="lefts",
|
|
columns=[dbscheme.Column("id", "@left", binding=True)],
|
|
),
|
|
dbscheme.Table(
|
|
name="rights",
|
|
columns=[dbscheme.Column("id", "@right", binding=True)],
|
|
),
|
|
],
|
|
)
|
|
|
|
|
|
def test_class_with_derived_and_repeated_property(generate, dir_param):
|
|
assert generate(
|
|
[
|
|
schema.Class(
|
|
name="Base",
|
|
pragmas={"group": dir_param.input},
|
|
derived={"Left", "Right"},
|
|
properties=[
|
|
schema.RepeatedProperty("rep", "Prop"),
|
|
],
|
|
),
|
|
schema.Class(name="Left", bases=["Base"]),
|
|
schema.Class(name="Right", bases=["Base"]),
|
|
]
|
|
) == dbscheme.Scheme(
|
|
src=schema_file.name,
|
|
includes=[],
|
|
declarations=[
|
|
dbscheme.Union(
|
|
lhs="@base",
|
|
rhs=["@left", "@right"],
|
|
),
|
|
dbscheme.Table(
|
|
name="base_reps",
|
|
keyset=dbscheme.KeySet(["id", "index"]),
|
|
columns=[
|
|
dbscheme.Column("id", "@base"),
|
|
dbscheme.Column("index", "int"),
|
|
dbscheme.Column("rep", "@prop"),
|
|
],
|
|
dir=dir_param.expected,
|
|
),
|
|
dbscheme.Table(
|
|
name="lefts",
|
|
columns=[dbscheme.Column("id", "@left", binding=True)],
|
|
),
|
|
dbscheme.Table(
|
|
name="rights",
|
|
columns=[dbscheme.Column("id", "@right", binding=True)],
|
|
),
|
|
],
|
|
)
|
|
|
|
|
|
def test_null_class(generate):
|
|
assert generate(
|
|
[
|
|
schema.Class(
|
|
name="Base",
|
|
derived={"W", "X", "Y", "Z", "Null"},
|
|
),
|
|
schema.Class(
|
|
name="W",
|
|
bases=["Base"],
|
|
properties=[
|
|
schema.SingleProperty("w", "W"),
|
|
schema.SingleProperty("x", "X"),
|
|
schema.OptionalProperty("y", "Y"),
|
|
schema.RepeatedProperty("z", "Z"),
|
|
],
|
|
),
|
|
schema.Class(
|
|
name="X",
|
|
bases=["Base"],
|
|
),
|
|
schema.Class(
|
|
name="Y",
|
|
bases=["Base"],
|
|
),
|
|
schema.Class(
|
|
name="Z",
|
|
bases=["Base"],
|
|
),
|
|
schema.Class(
|
|
name="Null",
|
|
bases=["Base"],
|
|
),
|
|
],
|
|
null="Null",
|
|
) == dbscheme.Scheme(
|
|
src=schema_file.name,
|
|
includes=[],
|
|
declarations=[
|
|
dbscheme.Union(
|
|
lhs="@base",
|
|
rhs=["@null", "@w", "@x", "@y", "@z"],
|
|
),
|
|
dbscheme.Table(
|
|
name="ws",
|
|
columns=[
|
|
dbscheme.Column("id", "@w", binding=True),
|
|
dbscheme.Column("w", "@w_or_none"),
|
|
dbscheme.Column("x", "@x_or_none"),
|
|
],
|
|
),
|
|
dbscheme.Table(
|
|
name="w_ies",
|
|
keyset=dbscheme.KeySet(["id"]),
|
|
columns=[
|
|
dbscheme.Column("id", "@w"),
|
|
dbscheme.Column("y", "@y_or_none"),
|
|
],
|
|
),
|
|
dbscheme.Table(
|
|
name="w_zs",
|
|
keyset=dbscheme.KeySet(["id", "index"]),
|
|
columns=[
|
|
dbscheme.Column("id", "@w"),
|
|
dbscheme.Column("index", "int"),
|
|
dbscheme.Column("z", "@z_or_none"),
|
|
],
|
|
),
|
|
dbscheme.Table(
|
|
name="xes",
|
|
columns=[
|
|
dbscheme.Column("id", "@x", binding=True),
|
|
],
|
|
),
|
|
dbscheme.Table(
|
|
name="ys",
|
|
columns=[
|
|
dbscheme.Column("id", "@y", binding=True),
|
|
],
|
|
),
|
|
dbscheme.Table(
|
|
name="zs",
|
|
columns=[
|
|
dbscheme.Column("id", "@z", binding=True),
|
|
],
|
|
),
|
|
dbscheme.Table(
|
|
name="nulls",
|
|
columns=[
|
|
dbscheme.Column("id", "@null", binding=True),
|
|
],
|
|
),
|
|
dbscheme.Union(
|
|
lhs="@w_or_none",
|
|
rhs=["@w", "@null"],
|
|
),
|
|
dbscheme.Union(
|
|
lhs="@x_or_none",
|
|
rhs=["@x", "@null"],
|
|
),
|
|
dbscheme.Union(
|
|
lhs="@y_or_none",
|
|
rhs=["@y", "@null"],
|
|
),
|
|
dbscheme.Union(
|
|
lhs="@z_or_none",
|
|
rhs=["@z", "@null"],
|
|
),
|
|
],
|
|
)
|
|
|
|
|
|
def test_synth_classes_ignored(generate):
|
|
assert generate(
|
|
[
|
|
schema.Class(name="A", pragmas={"synth": schema.SynthInfo()}),
|
|
schema.Class(name="B", pragmas={"synth": schema.SynthInfo(from_class="A")}),
|
|
schema.Class(
|
|
name="C", pragmas={"synth": schema.SynthInfo(on_arguments={"x": "A"})}
|
|
),
|
|
]
|
|
) == dbscheme.Scheme(
|
|
src=schema_file.name,
|
|
includes=[],
|
|
declarations=[],
|
|
)
|
|
|
|
|
|
def test_synth_derived_classes_ignored(generate):
|
|
assert generate(
|
|
[
|
|
schema.Class(name="A", derived={"B", "C"}),
|
|
schema.Class(name="B", bases=["A"], pragmas={"synth": schema.SynthInfo()}),
|
|
schema.Class(name="C", bases=["A"]),
|
|
]
|
|
) == dbscheme.Scheme(
|
|
src=schema_file.name,
|
|
includes=[],
|
|
declarations=[
|
|
dbscheme.Union("@a", ["@c"]),
|
|
dbscheme.Table(
|
|
name="cs",
|
|
columns=[
|
|
dbscheme.Column("id", "@c", binding=True),
|
|
],
|
|
),
|
|
],
|
|
)
|
|
|
|
|
|
def test_synth_properties_ignored(generate):
|
|
assert generate(
|
|
[
|
|
schema.Class(
|
|
name="A",
|
|
properties=[
|
|
schema.SingleProperty("x", "a"),
|
|
schema.SingleProperty("y", "b", synth=True),
|
|
schema.SingleProperty("z", "c"),
|
|
schema.OptionalProperty("foo", "bar", synth=True),
|
|
schema.RepeatedProperty("baz", "bazz", synth=True),
|
|
schema.RepeatedOptionalProperty("bazzz", "bazzzz", synth=True),
|
|
schema.RepeatedUnorderedProperty("bazzzzz", "bazzzzzz", synth=True),
|
|
],
|
|
),
|
|
]
|
|
) == dbscheme.Scheme(
|
|
src=schema_file.name,
|
|
includes=[],
|
|
declarations=[
|
|
dbscheme.Table(
|
|
name="as",
|
|
columns=[
|
|
dbscheme.Column("id", "@a", binding=True),
|
|
dbscheme.Column("x", "a"),
|
|
dbscheme.Column("z", "c"),
|
|
],
|
|
)
|
|
],
|
|
)
|
|
|
|
|
|
def test_table_conflict(generate):
|
|
with pytest.raises(dbschemegen.Error):
|
|
generate(
|
|
[
|
|
schema.Class(
|
|
"Foo",
|
|
properties=[
|
|
schema.OptionalProperty("bar", "FooBar"),
|
|
],
|
|
),
|
|
schema.Class("FooBar"),
|
|
]
|
|
)
|
|
|
|
|
|
def test_table_name_overrides(generate):
|
|
assert generate(
|
|
[
|
|
schema.Class(
|
|
"Obj",
|
|
properties=[
|
|
schema.OptionalProperty(
|
|
"x", "a", pragmas={"ql_db_table_name": "foo"}
|
|
),
|
|
schema.RepeatedProperty(
|
|
"y", "b", pragmas={"ql_db_table_name": "bar"}
|
|
),
|
|
schema.RepeatedOptionalProperty(
|
|
"z", "c", pragmas={"ql_db_table_name": "baz"}
|
|
),
|
|
schema.PredicateProperty(
|
|
"p", pragmas={"ql_db_table_name": "hello"}
|
|
),
|
|
schema.RepeatedUnorderedProperty(
|
|
"q", "d", pragmas={"ql_db_table_name": "world"}
|
|
),
|
|
],
|
|
),
|
|
]
|
|
) == dbscheme.Scheme(
|
|
src=schema_file.name,
|
|
includes=[],
|
|
declarations=[
|
|
dbscheme.Table(
|
|
name="objs",
|
|
columns=[
|
|
dbscheme.Column("id", "@obj", binding=True),
|
|
],
|
|
),
|
|
dbscheme.Table(
|
|
name="foo",
|
|
keyset=dbscheme.KeySet(["id"]),
|
|
columns=[
|
|
dbscheme.Column("id", "@obj"),
|
|
dbscheme.Column("x", "a"),
|
|
],
|
|
),
|
|
dbscheme.Table(
|
|
name="bar",
|
|
keyset=dbscheme.KeySet(["id", "index"]),
|
|
columns=[
|
|
dbscheme.Column("id", "@obj"),
|
|
dbscheme.Column("index", "int"),
|
|
dbscheme.Column("y", "b"),
|
|
],
|
|
),
|
|
dbscheme.Table(
|
|
name="baz",
|
|
keyset=dbscheme.KeySet(["id", "index"]),
|
|
columns=[
|
|
dbscheme.Column("id", "@obj"),
|
|
dbscheme.Column("index", "int"),
|
|
dbscheme.Column("z", "c"),
|
|
],
|
|
),
|
|
dbscheme.Table(
|
|
name="hello",
|
|
keyset=dbscheme.KeySet(["id"]),
|
|
columns=[
|
|
dbscheme.Column("id", "@obj"),
|
|
],
|
|
),
|
|
dbscheme.Table(
|
|
name="world",
|
|
columns=[
|
|
dbscheme.Column("id", "@obj"),
|
|
dbscheme.Column("q", "d"),
|
|
],
|
|
),
|
|
],
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(pytest.main([__file__] + sys.argv[1:]))
|