diff --git a/README.md b/README.md index fcb8f9d..7f68c92 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # asam-qc-openscenarioxml -This project implements the [ASAM OpenScenario XML Checker](checker_bundle_doc.md). +This project implements the [ASAM OpenScenario XML Checker Bundle](checker_bundle_doc.md). - [asam-qc-openscenarioxml](#asam-qc-openscenarioxml) - [Installation and usage](#installation-and-usage) @@ -27,8 +27,11 @@ asam-qc-openscenarioxml can be installed using pip. pip install asam-qc-openscenarioxml@git+https://github.com/asam-ev/qc-openscenarioxml@main ``` -**Note**: To install from different sources, you can replace `@main` with -your desired target. For example, `develop` branch as `@develop`. +**Note:** The above command will install `asam-qc-openscenarioxml` from the `main` branch. If you want to install `asam-qc-openscenarioxml` from another branch or tag, replace `@main` with the desired branch or tag. It is also possible to install from a local directory. + +```bash +pip install /home/user/qc-openscenarioxml +``` To run the application: diff --git a/checker_bundle_doc.md b/checker_bundle_doc.md index 2a12deb..514b2be 100644 --- a/checker_bundle_doc.md +++ b/checker_bundle_doc.md @@ -1,3 +1,4 @@ + # Checker bundle: xoscBundle * Build version: 0.1.0 @@ -41,7 +42,7 @@ ### check_asam_xosc_reference_control_uniquely_resolvable_entity_references -* Description: Input xml file must be valid according to the schema. +* Description: Reference names must be unique * Addressed rules: * asam.net:xosc:1.2.0:reference_control.uniquely_resolvable_entity_references diff --git a/poetry.lock b/poetry.lock index f0329c1..3aab2d9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -29,7 +29,7 @@ pydantic-xml = "^2.11.0" type = "git" url = "https://github.com/asam-ev/qc-baselib-py.git" reference = "develop" -resolved_reference = "f7ea664805bcce456ebd0ede93c852dd389c1944" +resolved_reference = "bfed12fc6f1bbd2cab97f74a6c9aa0e0faaef7b3" [[package]] name = "black" @@ -316,13 +316,13 @@ files = [ [[package]] name = "platformdirs" -version = "4.3.2" +version = "4.3.6" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" files = [ - {file = "platformdirs-4.3.2-py3-none-any.whl", hash = "sha256:eb1c8582560b34ed4ba105009a4badf7f6f85768b30126f351328507b2beb617"}, - {file = "platformdirs-4.3.2.tar.gz", hash = "sha256:9e5e27a08aa095dd127b9f2e764d74254f482fef22b0970773bfba79d091ab8c"}, + {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, + {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, ] [package.extras] @@ -347,18 +347,18 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pydantic" -version = "2.9.1" +version = "2.9.2" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.9.1-py3-none-any.whl", hash = "sha256:7aff4db5fdf3cf573d4b3c30926a510a10e19a0774d38fc4967f78beb6deb612"}, - {file = "pydantic-2.9.1.tar.gz", hash = "sha256:1363c7d975c7036df0db2b4a61f2e062fbc0aa5ab5f2772e0ffc7191a4f4bce2"}, + {file = "pydantic-2.9.2-py3-none-any.whl", hash = "sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12"}, + {file = "pydantic-2.9.2.tar.gz", hash = "sha256:d155cef71265d1e9807ed1c32b4c8deec042a44a50a4188b25ac67ecd81a9c0f"}, ] [package.dependencies] annotated-types = ">=0.6.0" -pydantic-core = "2.23.3" +pydantic-core = "2.23.4" typing-extensions = [ {version = ">=4.12.2", markers = "python_version >= \"3.13\""}, {version = ">=4.6.1", markers = "python_version < \"3.13\""}, @@ -370,100 +370,100 @@ timezone = ["tzdata"] [[package]] name = "pydantic-core" -version = "2.23.3" +version = "2.23.4" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.23.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:7f10a5d1b9281392f1bf507d16ac720e78285dfd635b05737c3911637601bae6"}, - {file = "pydantic_core-2.23.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3c09a7885dd33ee8c65266e5aa7fb7e2f23d49d8043f089989726391dd7350c5"}, - {file = "pydantic_core-2.23.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6470b5a1ec4d1c2e9afe928c6cb37eb33381cab99292a708b8cb9aa89e62429b"}, - {file = "pydantic_core-2.23.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9172d2088e27d9a185ea0a6c8cebe227a9139fd90295221d7d495944d2367700"}, - {file = "pydantic_core-2.23.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86fc6c762ca7ac8fbbdff80d61b2c59fb6b7d144aa46e2d54d9e1b7b0e780e01"}, - {file = "pydantic_core-2.23.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0cb80fd5c2df4898693aa841425ea1727b1b6d2167448253077d2a49003e0ed"}, - {file = "pydantic_core-2.23.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03667cec5daf43ac4995cefa8aaf58f99de036204a37b889c24a80927b629cec"}, - {file = "pydantic_core-2.23.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:047531242f8e9c2db733599f1c612925de095e93c9cc0e599e96cf536aaf56ba"}, - {file = "pydantic_core-2.23.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5499798317fff7f25dbef9347f4451b91ac2a4330c6669821c8202fd354c7bee"}, - {file = "pydantic_core-2.23.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bbb5e45eab7624440516ee3722a3044b83fff4c0372efe183fd6ba678ff681fe"}, - {file = "pydantic_core-2.23.3-cp310-none-win32.whl", hash = "sha256:8b5b3ed73abb147704a6e9f556d8c5cb078f8c095be4588e669d315e0d11893b"}, - {file = "pydantic_core-2.23.3-cp310-none-win_amd64.whl", hash = "sha256:2b603cde285322758a0279995b5796d64b63060bfbe214b50a3ca23b5cee3e83"}, - {file = "pydantic_core-2.23.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:c889fd87e1f1bbeb877c2ee56b63bb297de4636661cc9bbfcf4b34e5e925bc27"}, - {file = "pydantic_core-2.23.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea85bda3189fb27503af4c45273735bcde3dd31c1ab17d11f37b04877859ef45"}, - {file = "pydantic_core-2.23.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7f7f72f721223f33d3dc98a791666ebc6a91fa023ce63733709f4894a7dc611"}, - {file = "pydantic_core-2.23.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b2b55b0448e9da68f56b696f313949cda1039e8ec7b5d294285335b53104b61"}, - {file = "pydantic_core-2.23.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c24574c7e92e2c56379706b9a3f07c1e0c7f2f87a41b6ee86653100c4ce343e5"}, - {file = "pydantic_core-2.23.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f2b05e6ccbee333a8f4b8f4d7c244fdb7a979e90977ad9c51ea31261e2085ce0"}, - {file = "pydantic_core-2.23.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2c409ce1c219c091e47cb03feb3c4ed8c2b8e004efc940da0166aaee8f9d6c8"}, - {file = "pydantic_core-2.23.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d965e8b325f443ed3196db890d85dfebbb09f7384486a77461347f4adb1fa7f8"}, - {file = "pydantic_core-2.23.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f56af3a420fb1ffaf43ece3ea09c2d27c444e7c40dcb7c6e7cf57aae764f2b48"}, - {file = "pydantic_core-2.23.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5b01a078dd4f9a52494370af21aa52964e0a96d4862ac64ff7cea06e0f12d2c5"}, - {file = "pydantic_core-2.23.3-cp311-none-win32.whl", hash = "sha256:560e32f0df04ac69b3dd818f71339983f6d1f70eb99d4d1f8e9705fb6c34a5c1"}, - {file = "pydantic_core-2.23.3-cp311-none-win_amd64.whl", hash = "sha256:c744fa100fdea0d000d8bcddee95213d2de2e95b9c12be083370b2072333a0fa"}, - {file = "pydantic_core-2.23.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:e0ec50663feedf64d21bad0809f5857bac1ce91deded203efc4a84b31b2e4305"}, - {file = "pydantic_core-2.23.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:db6e6afcb95edbe6b357786684b71008499836e91f2a4a1e55b840955b341dbb"}, - {file = "pydantic_core-2.23.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98ccd69edcf49f0875d86942f4418a4e83eb3047f20eb897bffa62a5d419c8fa"}, - {file = "pydantic_core-2.23.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a678c1ac5c5ec5685af0133262103defb427114e62eafeda12f1357a12140162"}, - {file = "pydantic_core-2.23.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:01491d8b4d8db9f3391d93b0df60701e644ff0894352947f31fff3e52bd5c801"}, - {file = "pydantic_core-2.23.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fcf31facf2796a2d3b7fe338fe8640aa0166e4e55b4cb108dbfd1058049bf4cb"}, - {file = "pydantic_core-2.23.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7200fd561fb3be06827340da066df4311d0b6b8eb0c2116a110be5245dceb326"}, - {file = "pydantic_core-2.23.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dc1636770a809dee2bd44dd74b89cc80eb41172bcad8af75dd0bc182c2666d4c"}, - {file = "pydantic_core-2.23.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:67a5def279309f2e23014b608c4150b0c2d323bd7bccd27ff07b001c12c2415c"}, - {file = "pydantic_core-2.23.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:748bdf985014c6dd3e1e4cc3db90f1c3ecc7246ff5a3cd4ddab20c768b2f1dab"}, - {file = "pydantic_core-2.23.3-cp312-none-win32.whl", hash = "sha256:255ec6dcb899c115f1e2a64bc9ebc24cc0e3ab097775755244f77360d1f3c06c"}, - {file = "pydantic_core-2.23.3-cp312-none-win_amd64.whl", hash = "sha256:40b8441be16c1e940abebed83cd006ddb9e3737a279e339dbd6d31578b802f7b"}, - {file = "pydantic_core-2.23.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:6daaf5b1ba1369a22c8b050b643250e3e5efc6a78366d323294aee54953a4d5f"}, - {file = "pydantic_core-2.23.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d015e63b985a78a3d4ccffd3bdf22b7c20b3bbd4b8227809b3e8e75bc37f9cb2"}, - {file = "pydantic_core-2.23.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3fc572d9b5b5cfe13f8e8a6e26271d5d13f80173724b738557a8c7f3a8a3791"}, - {file = "pydantic_core-2.23.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f6bd91345b5163ee7448bee201ed7dd601ca24f43f439109b0212e296eb5b423"}, - {file = "pydantic_core-2.23.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc379c73fd66606628b866f661e8785088afe2adaba78e6bbe80796baf708a63"}, - {file = "pydantic_core-2.23.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbdce4b47592f9e296e19ac31667daed8753c8367ebb34b9a9bd89dacaa299c9"}, - {file = "pydantic_core-2.23.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc3cf31edf405a161a0adad83246568647c54404739b614b1ff43dad2b02e6d5"}, - {file = "pydantic_core-2.23.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8e22b477bf90db71c156f89a55bfe4d25177b81fce4aa09294d9e805eec13855"}, - {file = "pydantic_core-2.23.3-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:0a0137ddf462575d9bce863c4c95bac3493ba8e22f8c28ca94634b4a1d3e2bb4"}, - {file = "pydantic_core-2.23.3-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:203171e48946c3164fe7691fc349c79241ff8f28306abd4cad5f4f75ed80bc8d"}, - {file = "pydantic_core-2.23.3-cp313-none-win32.whl", hash = "sha256:76bdab0de4acb3f119c2a4bff740e0c7dc2e6de7692774620f7452ce11ca76c8"}, - {file = "pydantic_core-2.23.3-cp313-none-win_amd64.whl", hash = "sha256:37ba321ac2a46100c578a92e9a6aa33afe9ec99ffa084424291d84e456f490c1"}, - {file = "pydantic_core-2.23.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d063c6b9fed7d992bcbebfc9133f4c24b7a7f215d6b102f3e082b1117cddb72c"}, - {file = "pydantic_core-2.23.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6cb968da9a0746a0cf521b2b5ef25fc5a0bee9b9a1a8214e0a1cfaea5be7e8a4"}, - {file = "pydantic_core-2.23.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edbefe079a520c5984e30e1f1f29325054b59534729c25b874a16a5048028d16"}, - {file = "pydantic_core-2.23.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cbaaf2ef20d282659093913da9d402108203f7cb5955020bd8d1ae5a2325d1c4"}, - {file = "pydantic_core-2.23.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fb539d7e5dc4aac345846f290cf504d2fd3c1be26ac4e8b5e4c2b688069ff4cf"}, - {file = "pydantic_core-2.23.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e6f33503c5495059148cc486867e1d24ca35df5fc064686e631e314d959ad5b"}, - {file = "pydantic_core-2.23.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04b07490bc2f6f2717b10c3969e1b830f5720b632f8ae2f3b8b1542394c47a8e"}, - {file = "pydantic_core-2.23.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:03795b9e8a5d7fda05f3873efc3f59105e2dcff14231680296b87b80bb327295"}, - {file = "pydantic_core-2.23.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c483dab0f14b8d3f0df0c6c18d70b21b086f74c87ab03c59250dbf6d3c89baba"}, - {file = "pydantic_core-2.23.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8b2682038e255e94baf2c473dca914a7460069171ff5cdd4080be18ab8a7fd6e"}, - {file = "pydantic_core-2.23.3-cp38-none-win32.whl", hash = "sha256:f4a57db8966b3a1d1a350012839c6a0099f0898c56512dfade8a1fe5fb278710"}, - {file = "pydantic_core-2.23.3-cp38-none-win_amd64.whl", hash = "sha256:13dd45ba2561603681a2676ca56006d6dee94493f03d5cadc055d2055615c3ea"}, - {file = "pydantic_core-2.23.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:82da2f4703894134a9f000e24965df73cc103e31e8c31906cc1ee89fde72cbd8"}, - {file = "pydantic_core-2.23.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dd9be0a42de08f4b58a3cc73a123f124f65c24698b95a54c1543065baca8cf0e"}, - {file = "pydantic_core-2.23.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89b731f25c80830c76fdb13705c68fef6a2b6dc494402987c7ea9584fe189f5d"}, - {file = "pydantic_core-2.23.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c6de1ec30c4bb94f3a69c9f5f2182baeda5b809f806676675e9ef6b8dc936f28"}, - {file = "pydantic_core-2.23.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb68b41c3fa64587412b104294b9cbb027509dc2f6958446c502638d481525ef"}, - {file = "pydantic_core-2.23.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c3980f2843de5184656aab58698011b42763ccba11c4a8c35936c8dd6c7068c"}, - {file = "pydantic_core-2.23.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94f85614f2cba13f62c3c6481716e4adeae48e1eaa7e8bac379b9d177d93947a"}, - {file = "pydantic_core-2.23.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:510b7fb0a86dc8f10a8bb43bd2f97beb63cffad1203071dc434dac26453955cd"}, - {file = "pydantic_core-2.23.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1eba2f7ce3e30ee2170410e2171867ea73dbd692433b81a93758ab2de6c64835"}, - {file = "pydantic_core-2.23.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4b259fd8409ab84b4041b7b3f24dcc41e4696f180b775961ca8142b5b21d0e70"}, - {file = "pydantic_core-2.23.3-cp39-none-win32.whl", hash = "sha256:40d9bd259538dba2f40963286009bf7caf18b5112b19d2b55b09c14dde6db6a7"}, - {file = "pydantic_core-2.23.3-cp39-none-win_amd64.whl", hash = "sha256:5a8cd3074a98ee70173a8633ad3c10e00dcb991ecec57263aacb4095c5efb958"}, - {file = "pydantic_core-2.23.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f399e8657c67313476a121a6944311fab377085ca7f490648c9af97fc732732d"}, - {file = "pydantic_core-2.23.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:6b5547d098c76e1694ba85f05b595720d7c60d342f24d5aad32c3049131fa5c4"}, - {file = "pydantic_core-2.23.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0dda0290a6f608504882d9f7650975b4651ff91c85673341789a476b1159f211"}, - {file = "pydantic_core-2.23.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65b6e5da855e9c55a0c67f4db8a492bf13d8d3316a59999cfbaf98cc6e401961"}, - {file = "pydantic_core-2.23.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:09e926397f392059ce0afdcac920df29d9c833256354d0c55f1584b0b70cf07e"}, - {file = "pydantic_core-2.23.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:87cfa0ed6b8c5bd6ae8b66de941cece179281239d482f363814d2b986b79cedc"}, - {file = "pydantic_core-2.23.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e61328920154b6a44d98cabcb709f10e8b74276bc709c9a513a8c37a18786cc4"}, - {file = "pydantic_core-2.23.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ce3317d155628301d649fe5e16a99528d5680af4ec7aa70b90b8dacd2d725c9b"}, - {file = "pydantic_core-2.23.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e89513f014c6be0d17b00a9a7c81b1c426f4eb9224b15433f3d98c1a071f8433"}, - {file = "pydantic_core-2.23.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:4f62c1c953d7ee375df5eb2e44ad50ce2f5aff931723b398b8bc6f0ac159791a"}, - {file = "pydantic_core-2.23.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2718443bc671c7ac331de4eef9b673063b10af32a0bb385019ad61dcf2cc8f6c"}, - {file = "pydantic_core-2.23.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0d90e08b2727c5d01af1b5ef4121d2f0c99fbee692c762f4d9d0409c9da6541"}, - {file = "pydantic_core-2.23.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2b676583fc459c64146debea14ba3af54e540b61762dfc0613dc4e98c3f66eeb"}, - {file = "pydantic_core-2.23.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:50e4661f3337977740fdbfbae084ae5693e505ca2b3130a6d4eb0f2281dc43b8"}, - {file = "pydantic_core-2.23.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:68f4cf373f0de6abfe599a38307f4417c1c867ca381c03df27c873a9069cda25"}, - {file = "pydantic_core-2.23.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:59d52cf01854cb26c46958552a21acb10dd78a52aa34c86f284e66b209db8cab"}, - {file = "pydantic_core-2.23.3.tar.gz", hash = "sha256:3cb0f65d8b4121c1b015c60104a685feb929a29d7cf204387c7f2688c7974690"}, + {file = "pydantic_core-2.23.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b10bd51f823d891193d4717448fab065733958bdb6a6b351967bd349d48d5c9b"}, + {file = "pydantic_core-2.23.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4fc714bdbfb534f94034efaa6eadd74e5b93c8fa6315565a222f7b6f42ca1166"}, + {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63e46b3169866bd62849936de036f901a9356e36376079b05efa83caeaa02ceb"}, + {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed1a53de42fbe34853ba90513cea21673481cd81ed1be739f7f2efb931b24916"}, + {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cfdd16ab5e59fc31b5e906d1a3f666571abc367598e3e02c83403acabc092e07"}, + {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255a8ef062cbf6674450e668482456abac99a5583bbafb73f9ad469540a3a232"}, + {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a7cd62e831afe623fbb7aabbb4fe583212115b3ef38a9f6b71869ba644624a2"}, + {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f09e2ff1f17c2b51f2bc76d1cc33da96298f0a036a137f5440ab3ec5360b624f"}, + {file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e38e63e6f3d1cec5a27e0afe90a085af8b6806ee208b33030e65b6516353f1a3"}, + {file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0dbd8dbed2085ed23b5c04afa29d8fd2771674223135dc9bc937f3c09284d071"}, + {file = "pydantic_core-2.23.4-cp310-none-win32.whl", hash = "sha256:6531b7ca5f951d663c339002e91aaebda765ec7d61b7d1e3991051906ddde119"}, + {file = "pydantic_core-2.23.4-cp310-none-win_amd64.whl", hash = "sha256:7c9129eb40958b3d4500fa2467e6a83356b3b61bfff1b414c7361d9220f9ae8f"}, + {file = "pydantic_core-2.23.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:77733e3892bb0a7fa797826361ce8a9184d25c8dffaec60b7ffe928153680ba8"}, + {file = "pydantic_core-2.23.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b84d168f6c48fabd1f2027a3d1bdfe62f92cade1fb273a5d68e621da0e44e6d"}, + {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df49e7a0861a8c36d089c1ed57d308623d60416dab2647a4a17fe050ba85de0e"}, + {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff02b6d461a6de369f07ec15e465a88895f3223eb75073ffea56b84d9331f607"}, + {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:996a38a83508c54c78a5f41456b0103c30508fed9abcad0a59b876d7398f25fd"}, + {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d97683ddee4723ae8c95d1eddac7c192e8c552da0c73a925a89fa8649bf13eea"}, + {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:216f9b2d7713eb98cb83c80b9c794de1f6b7e3145eef40400c62e86cee5f4e1e"}, + {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6f783e0ec4803c787bcea93e13e9932edab72068f68ecffdf86a99fd5918878b"}, + {file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d0776dea117cf5272382634bd2a5c1b6eb16767c223c6a5317cd3e2a757c61a0"}, + {file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d5f7a395a8cf1621939692dba2a6b6a830efa6b3cee787d82c7de1ad2930de64"}, + {file = "pydantic_core-2.23.4-cp311-none-win32.whl", hash = "sha256:74b9127ffea03643e998e0c5ad9bd3811d3dac8c676e47db17b0ee7c3c3bf35f"}, + {file = "pydantic_core-2.23.4-cp311-none-win_amd64.whl", hash = "sha256:98d134c954828488b153d88ba1f34e14259284f256180ce659e8d83e9c05eaa3"}, + {file = "pydantic_core-2.23.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f3e0da4ebaef65158d4dfd7d3678aad692f7666877df0002b8a522cdf088f231"}, + {file = "pydantic_core-2.23.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f69a8e0b033b747bb3e36a44e7732f0c99f7edd5cea723d45bc0d6e95377ffee"}, + {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:723314c1d51722ab28bfcd5240d858512ffd3116449c557a1336cbe3919beb87"}, + {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb2802e667b7051a1bebbfe93684841cc9351004e2badbd6411bf357ab8d5ac8"}, + {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18ca8148bebe1b0a382a27a8ee60350091a6ddaf475fa05ef50dc35b5df6327"}, + {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33e3d65a85a2a4a0dc3b092b938a4062b1a05f3a9abde65ea93b233bca0e03f2"}, + {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:128585782e5bfa515c590ccee4b727fb76925dd04a98864182b22e89a4e6ed36"}, + {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:68665f4c17edcceecc112dfed5dbe6f92261fb9d6054b47d01bf6371a6196126"}, + {file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20152074317d9bed6b7a95ade3b7d6054845d70584216160860425f4fbd5ee9e"}, + {file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9261d3ce84fa1d38ed649c3638feefeae23d32ba9182963e465d58d62203bd24"}, + {file = "pydantic_core-2.23.4-cp312-none-win32.whl", hash = "sha256:4ba762ed58e8d68657fc1281e9bb72e1c3e79cc5d464be146e260c541ec12d84"}, + {file = "pydantic_core-2.23.4-cp312-none-win_amd64.whl", hash = "sha256:97df63000f4fea395b2824da80e169731088656d1818a11b95f3b173747b6cd9"}, + {file = "pydantic_core-2.23.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7530e201d10d7d14abce4fb54cfe5b94a0aefc87da539d0346a484ead376c3cc"}, + {file = "pydantic_core-2.23.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df933278128ea1cd77772673c73954e53a1c95a4fdf41eef97c2b779271bd0bd"}, + {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cb3da3fd1b6a5d0279a01877713dbda118a2a4fc6f0d821a57da2e464793f05"}, + {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c6dcb030aefb668a2b7009c85b27f90e51e6a3b4d5c9bc4c57631292015b0d"}, + {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:696dd8d674d6ce621ab9d45b205df149399e4bb9aa34102c970b721554828510"}, + {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2971bb5ffe72cc0f555c13e19b23c85b654dd2a8f7ab493c262071377bfce9f6"}, + {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8394d940e5d400d04cad4f75c0598665cbb81aecefaca82ca85bd28264af7f9b"}, + {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dff76e0602ca7d4cdaacc1ac4c005e0ce0dcfe095d5b5259163a80d3a10d327"}, + {file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7d32706badfe136888bdea71c0def994644e09fff0bfe47441deaed8e96fdbc6"}, + {file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed541d70698978a20eb63d8c5d72f2cc6d7079d9d90f6b50bad07826f1320f5f"}, + {file = "pydantic_core-2.23.4-cp313-none-win32.whl", hash = "sha256:3d5639516376dce1940ea36edf408c554475369f5da2abd45d44621cb616f769"}, + {file = "pydantic_core-2.23.4-cp313-none-win_amd64.whl", hash = "sha256:5a1504ad17ba4210df3a045132a7baeeba5a200e930f57512ee02909fc5c4cb5"}, + {file = "pydantic_core-2.23.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d4488a93b071c04dc20f5cecc3631fc78b9789dd72483ba15d423b5b3689b555"}, + {file = "pydantic_core-2.23.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:81965a16b675b35e1d09dd14df53f190f9129c0202356ed44ab2728b1c905658"}, + {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ffa2ebd4c8530079140dd2d7f794a9d9a73cbb8e9d59ffe24c63436efa8f271"}, + {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:61817945f2fe7d166e75fbfb28004034b48e44878177fc54d81688e7b85a3665"}, + {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29d2c342c4bc01b88402d60189f3df065fb0dda3654744d5a165a5288a657368"}, + {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5e11661ce0fd30a6790e8bcdf263b9ec5988e95e63cf901972107efc49218b13"}, + {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d18368b137c6295db49ce7218b1a9ba15c5bc254c96d7c9f9e924a9bc7825ad"}, + {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ec4e55f79b1c4ffb2eecd8a0cfba9955a2588497d96851f4c8f99aa4a1d39b12"}, + {file = "pydantic_core-2.23.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:374a5e5049eda9e0a44c696c7ade3ff355f06b1fe0bb945ea3cac2bc336478a2"}, + {file = "pydantic_core-2.23.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5c364564d17da23db1106787675fc7af45f2f7b58b4173bfdd105564e132e6fb"}, + {file = "pydantic_core-2.23.4-cp38-none-win32.whl", hash = "sha256:d7a80d21d613eec45e3d41eb22f8f94ddc758a6c4720842dc74c0581f54993d6"}, + {file = "pydantic_core-2.23.4-cp38-none-win_amd64.whl", hash = "sha256:5f5ff8d839f4566a474a969508fe1c5e59c31c80d9e140566f9a37bba7b8d556"}, + {file = "pydantic_core-2.23.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a4fa4fc04dff799089689f4fd502ce7d59de529fc2f40a2c8836886c03e0175a"}, + {file = "pydantic_core-2.23.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a7df63886be5e270da67e0966cf4afbae86069501d35c8c1b3b6c168f42cb36"}, + {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcedcd19a557e182628afa1d553c3895a9f825b936415d0dbd3cd0bbcfd29b4b"}, + {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f54b118ce5de9ac21c363d9b3caa6c800341e8c47a508787e5868c6b79c9323"}, + {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86d2f57d3e1379a9525c5ab067b27dbb8a0642fb5d454e17a9ac434f9ce523e3"}, + {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de6d1d1b9e5101508cb37ab0d972357cac5235f5c6533d1071964c47139257df"}, + {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1278e0d324f6908e872730c9102b0112477a7f7cf88b308e4fc36ce1bdb6d58c"}, + {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a6b5099eeec78827553827f4c6b8615978bb4b6a88e5d9b93eddf8bb6790f55"}, + {file = "pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e55541f756f9b3ee346b840103f32779c695a19826a4c442b7954550a0972040"}, + {file = "pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a5c7ba8ffb6d6f8f2ab08743be203654bb1aaa8c9dcb09f82ddd34eadb695605"}, + {file = "pydantic_core-2.23.4-cp39-none-win32.whl", hash = "sha256:37b0fe330e4a58d3c58b24d91d1eb102aeec675a3db4c292ec3928ecd892a9a6"}, + {file = "pydantic_core-2.23.4-cp39-none-win_amd64.whl", hash = "sha256:1498bec4c05c9c787bde9125cfdcc63a41004ff167f495063191b863399b1a29"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f455ee30a9d61d3e1a15abd5068827773d6e4dc513e795f380cdd59932c782d5"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1e90d2e3bd2c3863d48525d297cd143fe541be8bbf6f579504b9712cb6b643ec"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e203fdf807ac7e12ab59ca2bfcabb38c7cf0b33c41efeb00f8e5da1d86af480"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e08277a400de01bc72436a0ccd02bdf596631411f592ad985dcee21445bd0068"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f220b0eea5965dec25480b6333c788fb72ce5f9129e8759ef876a1d805d00801"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d06b0c8da4f16d1d1e352134427cb194a0a6e19ad5db9161bf32b2113409e728"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ba1a0996f6c2773bd83e63f18914c1de3c9dd26d55f4ac302a7efe93fb8e7433"}, + {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:9a5bce9d23aac8f0cf0836ecfc033896aa8443b501c58d0602dbfd5bd5b37753"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:78ddaaa81421a29574a682b3179d4cf9e6d405a09b99d93ddcf7e5239c742e21"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:883a91b5dd7d26492ff2f04f40fbb652de40fcc0afe07e8129e8ae779c2110eb"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88ad334a15b32a791ea935af224b9de1bf99bcd62fabf745d5f3442199d86d59"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:233710f069d251feb12a56da21e14cca67994eab08362207785cf8c598e74577"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:19442362866a753485ba5e4be408964644dd6a09123d9416c54cd49171f50744"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:624e278a7d29b6445e4e813af92af37820fafb6dcc55c012c834f9e26f9aaaef"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f5ef8f42bec47f21d07668a043f077d507e5bf4e668d5c6dfe6aaba89de1a5b8"}, + {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:aea443fffa9fbe3af1a9ba721a87f926fe548d32cab71d188a6ede77d0ff244e"}, + {file = "pydantic_core-2.23.4.tar.gz", hash = "sha256:2584f7cf844ac4d970fba483a717dbe10c1c1c96a969bf65d61ffe94df1b2863"}, ] [package.dependencies] diff --git a/qc_openscenario/__init__.py b/qc_openscenario/__init__.py index 137b3cc..0dc6a13 100644 --- a/qc_openscenario/__init__.py +++ b/qc_openscenario/__init__.py @@ -1,2 +1,3 @@ from . import constants as constants from . import checks as checks +from . import basic_preconditions as basic_preconditions diff --git a/qc_openscenario/checks/reference_checker/reference_checker_precondition.py b/qc_openscenario/basic_preconditions.py similarity index 93% rename from qc_openscenario/checks/reference_checker/reference_checker_precondition.py rename to qc_openscenario/basic_preconditions.py index 87ecdfa..cbb96ac 100644 --- a/qc_openscenario/checks/reference_checker/reference_checker_precondition.py +++ b/qc_openscenario/basic_preconditions.py @@ -7,7 +7,7 @@ from qc_openscenario.checks.schema_checker import valid_schema -PRECONDITIONS = { +CHECKER_PRECONDITIONS = { valid_xml_document.CHECKER_ID, root_tag_is_openscenario.CHECKER_ID, fileheader_is_present.CHECKER_ID, diff --git a/qc_openscenario/checks/basic_checker/__init__.py b/qc_openscenario/checks/basic_checker/__init__.py index 6d99129..404da2f 100644 --- a/qc_openscenario/checks/basic_checker/__init__.py +++ b/qc_openscenario/checks/basic_checker/__init__.py @@ -1,4 +1,3 @@ -from . import basic_checker as basic_checker from . import valid_xml_document as valid_xml_document from . import root_tag_is_openscenario as root_tag_is_openscenario from . import fileheader_is_present as fileheader_is_present diff --git a/qc_openscenario/checks/basic_checker/basic_checker.py b/qc_openscenario/checks/basic_checker/basic_checker.py deleted file mode 100644 index 9227674..0000000 --- a/qc_openscenario/checks/basic_checker/basic_checker.py +++ /dev/null @@ -1,63 +0,0 @@ -import logging -import os - -from lxml import etree - -from qc_baselib import Configuration, Result, StatusType - -from qc_openscenario import constants -from qc_openscenario.checks import utils, models - -from qc_openscenario.checks.basic_checker import ( - valid_xml_document, - root_tag_is_openscenario, - fileheader_is_present, - version_is_defined, -) - - -def run_checks(config: Configuration, result: Result) -> models.CheckerData: - logging.info("Executing basic checks") - - xml_file_path = config.get_config_param("InputFile") - - valid_xml_document.check_rule(xml_file_path, result) - - root = None - if result.all_checkers_completed_without_issue({valid_xml_document.CHECKER_ID}): - root = utils.get_root_without_default_namespace(xml_file_path) - - root_tag_is_openscenario.check_rule(root, result) - fileheader_is_present.check_rule(root, result) - version_is_defined.check_rule(root, result) - - checker_data = None - - if result.all_checkers_completed_without_issue( - { - valid_xml_document.CHECKER_ID, - root_tag_is_openscenario.CHECKER_ID, - fileheader_is_present.CHECKER_ID, - version_is_defined.CHECKER_ID, - } - ): - xosc_schema_version = utils.get_standard_schema_version(root) - xodr_root = utils.get_xodr_road_network(xml_file_path, root) - checker_data = models.CheckerData( - input_file_xml_root=root, - config=config, - result=result, - schema_version=xosc_schema_version, - xodr_root=xodr_root, - ) - else: - logging.info("Error found in basic rules!") - checker_data = models.CheckerData( - input_file_xml_root=None, - config=config, - result=result, - schema_version=None, - xodr_root=None, - ) - - return checker_data diff --git a/qc_openscenario/checks/basic_checker/fileheader_is_present.py b/qc_openscenario/checks/basic_checker/fileheader_is_present.py index 3b81615..014fc57 100644 --- a/qc_openscenario/checks/basic_checker/fileheader_is_present.py +++ b/qc_openscenario/checks/basic_checker/fileheader_is_present.py @@ -1,8 +1,8 @@ import logging -from lxml import etree -from qc_baselib import IssueSeverity, Result, StatusType +from qc_baselib import IssueSeverity from qc_openscenario import constants +from qc_openscenario.checks import models from qc_openscenario.checks.basic_checker import ( valid_xml_document, @@ -10,10 +10,15 @@ ) CHECKER_ID = "check_asam_xosc_xml_fileheader_is_present" -PRECONDITIONS = {valid_xml_document.CHECKER_ID, root_tag_is_openscenario.CHECKER_ID} +CHECKER_DESCRIPTION = "Below the root element a tag with FileHeader must be defined." +CHECKER_PRECONDITIONS = { + valid_xml_document.CHECKER_ID, + root_tag_is_openscenario.CHECKER_ID, +} +RULE_UID = "asam.net:xosc:1.0.0:xml.fileheader_is_present" -def check_rule(tree: etree._ElementTree, result: Result) -> None: +def check_rule(checker_data: models.CheckerData) -> None: """ Below the root element a tag with FileHeader must be defined. @@ -22,31 +27,7 @@ def check_rule(tree: etree._ElementTree, result: Result) -> None: """ logging.info("Executing fileheader_is_present check") - result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="Below the root element a tag with FileHeader must be defined.", - ) - - rule_uid = result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting="1.0.0", - rule_full_name="xml.fileheader_is_present", - ) - - if not result.all_checkers_completed_without_issue(PRECONDITIONS): - result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - root = tree.getroot() + root = checker_data.input_file_xml_root.getroot() is_valid = False # Check if root contains a tag 'FileHeader' @@ -60,24 +41,18 @@ def check_rule(tree: etree._ElementTree, result: Result) -> None: if not is_valid: - issue_id = result.register_issue( + issue_id = checker_data.result.register_issue( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, - description="Issue flagging when no FileHeader is found under root element", + description="No FileHeader found under root element", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) - result.add_xml_location( + checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, issue_id=issue_id, - xpath=tree.getpath(root), + xpath=checker_data.input_file_xml_root.getpath(root), description=f'No child element "FileHeader"', ) - - result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/basic_checker/root_tag_is_openscenario.py b/qc_openscenario/checks/basic_checker/root_tag_is_openscenario.py index cfd8ce2..e822dff 100644 --- a/qc_openscenario/checks/basic_checker/root_tag_is_openscenario.py +++ b/qc_openscenario/checks/basic_checker/root_tag_is_openscenario.py @@ -1,16 +1,18 @@ import logging -from lxml import etree -from qc_baselib import IssueSeverity, Result, StatusType +from qc_baselib import IssueSeverity from qc_openscenario import constants +from qc_openscenario.checks import models from qc_openscenario.checks.basic_checker import valid_xml_document CHECKER_ID = "check_asam_xosc_xml_root_tag_is_openscenario" -PRECONDITIONS = {valid_xml_document.CHECKER_ID} +CHECKER_DESCRIPTION = "The root element of a valid XML document must be OpenSCENARIO." +CHECKER_PRECONDITIONS = {valid_xml_document.CHECKER_ID} +RULE_UID = "asam.net:xosc:1.0.0:xml.root_tag_is_openscenario" -def check_rule(tree: etree._ElementTree, result: Result) -> None: +def check_rule(checker_data: models.CheckerData) -> None: """ The root element of a valid XML document must be OpenSCENARIO @@ -19,31 +21,7 @@ def check_rule(tree: etree._ElementTree, result: Result) -> None: """ logging.info("Executing root_tag_is_openscenario check") - result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="The root element of a valid XML document must be OpenSCENARIO.", - ) - - rule_uid = result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting="1.0.0", - rule_full_name="xml.root_tag_is_openscenario", - ) - - if not result.all_checkers_completed_without_issue(PRECONDITIONS): - result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - root = tree.getroot() + root = checker_data.input_file_xml_root.getroot() is_valid = False if root.tag == "OpenSCENARIO": @@ -55,24 +33,18 @@ def check_rule(tree: etree._ElementTree, result: Result) -> None: if not is_valid: - issue_id = result.register_issue( + issue_id = checker_data.result.register_issue( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, - description="Issue flagging when root tag is not OpenSCENARIO", + description="Root tag is not OpenSCENARIO", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) - result.add_xml_location( + checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, issue_id=issue_id, - xpath=tree.getpath(root), + xpath=checker_data.input_file_xml_root.getpath(root), description=f"Root is not OpenSCENARIO", ) - - result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/basic_checker/valid_xml_document.py b/qc_openscenario/checks/basic_checker/valid_xml_document.py index 2f83fc7..2e2b7c3 100644 --- a/qc_openscenario/checks/basic_checker/valid_xml_document.py +++ b/qc_openscenario/checks/basic_checker/valid_xml_document.py @@ -2,10 +2,14 @@ from lxml import etree -from qc_baselib import Result, IssueSeverity, StatusType +from qc_baselib import IssueSeverity from qc_openscenario import constants +from qc_openscenario.checks import models CHECKER_ID = "check_asam_xosc_xml_valid_xml_document" +CHECKER_DESCRIPTION = "The given file to check must be a valid XML document." +CHECKER_PRECONDITIONS = set() +RULE_UID = "asam.net:xosc:1.0.0:xml.valid_xml_document" def _is_xml_doc(file_path: str) -> tuple[bool, tuple[int, int]]: @@ -21,7 +25,7 @@ def _is_xml_doc(file_path: str) -> tuple[bool, tuple[int, int]]: return False, (e.lineno, e.offset) -def check_rule(input_xml_file_path: str, result: Result) -> None: +def check_rule(checker_data: models.CheckerData) -> None: """ Implements a rule to check if input file is a valid xml document @@ -30,34 +34,19 @@ def check_rule(input_xml_file_path: str, result: Result) -> None: """ logging.info("Executing valid_xml_document check") - result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="The given file to check must be a valid XML document.", - ) - - rule_uid = result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting="1.0.0", - rule_full_name="xml.valid_xml_document", - ) - - is_valid, error_location = _is_xml_doc(input_xml_file_path) + is_valid, error_location = _is_xml_doc(checker_data.xml_file_path) if not is_valid: - issue_id = result.register_issue( + issue_id = checker_data.result.register_issue( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, description="The input file is not a valid xml document", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) - result.add_file_location( + checker_data.result.add_file_location( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, issue_id=issue_id, @@ -65,9 +54,3 @@ def check_rule(input_xml_file_path: str, result: Result) -> None: column=error_location[1], description=f"Invalid xml file.", ) - - result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/basic_checker/version_is_defined.py b/qc_openscenario/checks/basic_checker/version_is_defined.py index 397a9ad..0fd8e09 100644 --- a/qc_openscenario/checks/basic_checker/version_is_defined.py +++ b/qc_openscenario/checks/basic_checker/version_is_defined.py @@ -1,8 +1,9 @@ import logging -from lxml import etree -from qc_baselib import IssueSeverity, Result, StatusType + +from qc_baselib import IssueSeverity, StatusType from qc_openscenario import constants +from qc_openscenario.checks import models from qc_openscenario.checks.basic_checker import ( valid_xml_document, @@ -11,11 +12,13 @@ ) CHECKER_ID = "check_asam_xosc_xml_version_is_defined" -PRECONDITIONS = { +CHECKER_DESCRIPTION = "The FileHeader tag must have the attributes revMajor and revMinor and of type unsignedShort." +CHECKER_PRECONDITIONS = { valid_xml_document.CHECKER_ID, root_tag_is_openscenario.CHECKER_ID, fileheader_is_present.CHECKER_ID, } +RULE_UID = "asam.net:xosc:1.0.0:xml.version_is_defined" def is_unsigned_short(value: int) -> bool: @@ -27,7 +30,7 @@ def is_unsigned_short(value: int) -> bool: return False -def check_rule(tree: etree._ElementTree, result: Result) -> None: +def check_rule(checker_data: models.CheckerData) -> None: """ The FileHeader tag must have the attributes revMajor and revMinor and of type unsignedShort. @@ -36,31 +39,7 @@ def check_rule(tree: etree._ElementTree, result: Result) -> None: """ logging.info("Executing version_is_defined check") - result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="The FileHeader tag must have the attributes revMajor and revMinor and of type unsignedShort.", - ) - - rule_uid = result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting="1.0.0", - rule_full_name="xml.version_is_defined", - ) - - if not result.all_checkers_completed_without_issue(PRECONDITIONS): - result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - root = tree.getroot() + root = checker_data.input_file_xml_root.getroot() is_valid = True # Check if root contains a tag 'FileHeader' @@ -91,24 +70,18 @@ def check_rule(tree: etree._ElementTree, result: Result) -> None: if not is_valid: - issue_id = result.register_issue( + issue_id = checker_data.result.register_issue( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, - description="Issue flagging when revMajor revMinor attribute of FileHeader are missing or invalid", + description="Version attributes revMajor-revMinor missing or invalid", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) - result.add_xml_location( + checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, issue_id=issue_id, - xpath=tree.getpath(file_header_tag), + xpath=checker_data.input_file_xml_root.getpath(file_header_tag), description=f'"FileHeader" tag has invalid or missing version info', ) - - result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/data_type_checker/__init__.py b/qc_openscenario/checks/data_type_checker/__init__.py index c05a5a3..7338e41 100644 --- a/qc_openscenario/checks/data_type_checker/__init__.py +++ b/qc_openscenario/checks/data_type_checker/__init__.py @@ -1,5 +1,3 @@ -from . import data_type_checker_precondition as data_type_checker_precondition -from . import data_type_checker as data_type_checker from . import allowed_operators as allowed_operators from . import ( non_negative_transition_time_in_light_state_action as non_negative_transition_time_in_light_state_action, diff --git a/qc_openscenario/checks/data_type_checker/allowed_operators.py b/qc_openscenario/checks/data_type_checker/allowed_operators.py index dd24e19..979fd66 100644 --- a/qc_openscenario/checks/data_type_checker/allowed_operators.py +++ b/qc_openscenario/checks/data_type_checker/allowed_operators.py @@ -10,13 +10,15 @@ from qc_openscenario import constants from qc_openscenario.checks import utils, models -from qc_openscenario.checks.data_type_checker import data_type_checker_precondition +from qc_openscenario import basic_preconditions import re import enum CHECKER_ID = "check_asam_xosc_data_type_allowed_operators" -MIN_RULE_VERSION = "1.2.0" +CHECKER_DESCRIPTION = "Expressions in OpenSCENARIO must only use the allowed operands." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = "asam.net:xosc:1.2.0:data_type.allowed_operators" ALLOWED_OPERANDS = set() ALLOWED_OPERANDS.add("-") @@ -105,45 +107,6 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing allowed_operators check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="Expressions in OpenSCENARIO must only use the allowed operands.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="data_type.allowed_operators", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - data_type_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - tree = checker_data.input_file_xml_root root = tree.getroot() attributes = get_all_attributes(tree, root) @@ -187,9 +150,9 @@ def check_rule(checker_data: models.CheckerData) -> None: issue_id = checker_data.result.register_issue( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, - description="Issue flagging invalid operand is used within expression", + description="Invalid operand used within expression", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, @@ -198,9 +161,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=xpath, description=f"Invalid operand {token} used", ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/data_type_checker/data_type_checker.py b/qc_openscenario/checks/data_type_checker/data_type_checker.py deleted file mode 100644 index f6e4255..0000000 --- a/qc_openscenario/checks/data_type_checker/data_type_checker.py +++ /dev/null @@ -1,17 +0,0 @@ -import logging - -from qc_openscenario.checks import models - -from qc_openscenario.checks.data_type_checker import ( - allowed_operators, - non_negative_transition_time_in_light_state_action, - positive_duration_in_phase, -) - - -def run_checks(checker_data: models.CheckerData) -> None: - logging.info("Executing data_type checks") - - allowed_operators.check_rule(checker_data) - non_negative_transition_time_in_light_state_action.check_rule(checker_data) - positive_duration_in_phase.check_rule(checker_data) diff --git a/qc_openscenario/checks/data_type_checker/data_type_checker_precondition.py b/qc_openscenario/checks/data_type_checker/data_type_checker_precondition.py deleted file mode 100644 index 87ecdfa..0000000 --- a/qc_openscenario/checks/data_type_checker/data_type_checker_precondition.py +++ /dev/null @@ -1,16 +0,0 @@ -from qc_openscenario.checks.basic_checker import ( - valid_xml_document, - root_tag_is_openscenario, - fileheader_is_present, - version_is_defined, -) - -from qc_openscenario.checks.schema_checker import valid_schema - -PRECONDITIONS = { - valid_xml_document.CHECKER_ID, - root_tag_is_openscenario.CHECKER_ID, - fileheader_is_present.CHECKER_ID, - version_is_defined.CHECKER_ID, - valid_schema.CHECKER_ID, -} diff --git a/qc_openscenario/checks/data_type_checker/non_negative_transition_time_in_light_state_action.py b/qc_openscenario/checks/data_type_checker/non_negative_transition_time_in_light_state_action.py index 0459a4c..4fc7561 100644 --- a/qc_openscenario/checks/data_type_checker/non_negative_transition_time_in_light_state_action.py +++ b/qc_openscenario/checks/data_type_checker/non_negative_transition_time_in_light_state_action.py @@ -5,12 +5,16 @@ from qc_openscenario import constants from qc_openscenario.checks import utils, models -from qc_openscenario.checks.data_type_checker import data_type_checker_precondition +from qc_openscenario import basic_preconditions CHECKER_ID = ( "check_asam_xosc_data_type_non_negative_transition_time_in_light_state_action" ) -MIN_RULE_VERSION = "1.2.0" +CHECKER_DESCRIPTION = "Expressions in OpenSCENARIO must only use the allowed operands." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = ( + "asam.net:xosc:1.2.0:data_type.non_negative_transition_time_in_light_state_action" +) def check_rule(checker_data: models.CheckerData) -> None: @@ -30,45 +34,6 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing non_negative_transition_time_in_light_state_action check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="Expressions in OpenSCENARIO must only use the allowed operands.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="data_type.non_negative_transition_time_in_light_state_action", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - data_type_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - root = checker_data.input_file_xml_root light_state_nodes = root.findall(".//LightStateAction") @@ -110,19 +75,25 @@ def check_rule(checker_data: models.CheckerData) -> None: logging.debug(f"current_transition_time: {current_transition_time}") if not utils.is_xsd_double(current_transition_time): - logging.error( - f"Cannot convert '{current_transition_time}' to double as it does not match xsd:double pattern. Skipping check..." - ) - checker_data.result.set_checker_status( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, status=StatusType.SKIPPED, ) + checker_data.result.add_checker_summary( + constants.BUNDLE_NAME, + CHECKER_ID, + f"Cannot convert '{current_transition_time}' to double as it does not match xsd:double pattern. Skip the check.", + ) + return - current_numeric_value = float(current_transition_time) + current_numeric_value = utils.to_float(current_transition_time) + + if current_numeric_value is None: + continue + has_issue = current_numeric_value < 0 if has_issue: @@ -131,9 +102,9 @@ def check_rule(checker_data: models.CheckerData) -> None: issue_id = checker_data.result.register_issue( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, - description="Issue transitionTime in LightStateAction node is negative", + description="transitionTime in LightStateAction node is negative", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, @@ -142,9 +113,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=xpath, description=f"transitionTime duration {current_numeric_value} is negative", ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/data_type_checker/positive_duration_in_phase.py b/qc_openscenario/checks/data_type_checker/positive_duration_in_phase.py index 82215be..e901a2f 100644 --- a/qc_openscenario/checks/data_type_checker/positive_duration_in_phase.py +++ b/qc_openscenario/checks/data_type_checker/positive_duration_in_phase.py @@ -5,10 +5,12 @@ from qc_openscenario import constants from qc_openscenario.checks import utils, models -from qc_openscenario.checks.data_type_checker import data_type_checker_precondition +from qc_openscenario import basic_preconditions CHECKER_ID = "check_asam_xosc_positive_duration_in_phase" -MIN_RULE_VERSION = "1.2.0" +CHECKER_DESCRIPTION = "Expressions in OpenSCENARIO must only use the allowed operands." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = "asam.net:xosc:1.2.0:data_type.positive_duration_in_phase" def check_rule(checker_data: models.CheckerData) -> None: @@ -28,45 +30,6 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing positive_duration_in_phase check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="Expressions in OpenSCENARIO must only use the allowed operands.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="data_type.positive_duration_in_phase", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - data_type_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - root = checker_data.input_file_xml_root phase_nodes = root.findall(".//Phase") @@ -99,19 +62,25 @@ def check_rule(checker_data: models.CheckerData) -> None: current_duration = current_duration_param_value if not utils.is_xsd_double(current_duration): - logging.error( - f"Cannot convert '{current_duration}' to double as it does not match xsd:double pattern. Skipping check..." - ) - checker_data.result.set_checker_status( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, status=StatusType.SKIPPED, ) + checker_data.result.add_checker_summary( + constants.BUNDLE_NAME, + CHECKER_ID, + f"Cannot convert '{current_duration}' to double as it does not match xsd:double pattern. Skip the check.", + ) + return - current_numeric_value = float(current_duration) + current_numeric_value = utils.to_float(current_duration) + + if current_numeric_value is None: + continue + has_issue = current_numeric_value < 0 if has_issue: @@ -120,9 +89,9 @@ def check_rule(checker_data: models.CheckerData) -> None: issue_id = checker_data.result.register_issue( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, - description="Issue flagging when attribute “duration” in the complex type “Phase” is negative", + description="Attribute “duration” in the complex type “Phase” is negative", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, @@ -131,9 +100,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=xpath, description=f"Phase duration {current_numeric_value} is negative", ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/models.py b/qc_openscenario/checks/models.py index b0c703c..aacd3d7 100644 --- a/qc_openscenario/checks/models.py +++ b/qc_openscenario/checks/models.py @@ -8,10 +8,11 @@ @dataclass class CheckerData: - input_file_xml_root: etree._ElementTree + xml_file_path: str + input_file_xml_root: Union[None, etree._ElementTree] config: Configuration result: Result - schema_version: str + schema_version: Union[None, str] xodr_root: Union[None, etree._ElementTree] diff --git a/qc_openscenario/checks/parameters_checker/__init__.py b/qc_openscenario/checks/parameters_checker/__init__.py index 919e248..8c8e504 100644 --- a/qc_openscenario/checks/parameters_checker/__init__.py +++ b/qc_openscenario/checks/parameters_checker/__init__.py @@ -1,5 +1,3 @@ -from . import parameters_checker as parameters_checker -from . import parameter_checker_precondition as parameter_checker_precondition from . import ( valid_parameter_declaration_in_catalogs as valid_parameter_declaration_in_catalogs, ) diff --git a/qc_openscenario/checks/parameters_checker/parameter_checker_precondition.py b/qc_openscenario/checks/parameters_checker/parameter_checker_precondition.py deleted file mode 100644 index 87ecdfa..0000000 --- a/qc_openscenario/checks/parameters_checker/parameter_checker_precondition.py +++ /dev/null @@ -1,16 +0,0 @@ -from qc_openscenario.checks.basic_checker import ( - valid_xml_document, - root_tag_is_openscenario, - fileheader_is_present, - version_is_defined, -) - -from qc_openscenario.checks.schema_checker import valid_schema - -PRECONDITIONS = { - valid_xml_document.CHECKER_ID, - root_tag_is_openscenario.CHECKER_ID, - fileheader_is_present.CHECKER_ID, - version_is_defined.CHECKER_ID, - valid_schema.CHECKER_ID, -} diff --git a/qc_openscenario/checks/parameters_checker/parameters_checker.py b/qc_openscenario/checks/parameters_checker/parameters_checker.py deleted file mode 100644 index e9d7ae6..0000000 --- a/qc_openscenario/checks/parameters_checker/parameters_checker.py +++ /dev/null @@ -1,10 +0,0 @@ -import logging -from qc_openscenario.checks import models -from qc_openscenario.checks.parameters_checker import ( - valid_parameter_declaration_in_catalogs, -) - - -def run_checks(checker_data: models.CheckerData) -> None: - logging.info("Executing parameters checks") - valid_parameter_declaration_in_catalogs.check_rule(checker_data) diff --git a/qc_openscenario/checks/parameters_checker/valid_parameter_declaration_in_catalogs.py b/qc_openscenario/checks/parameters_checker/valid_parameter_declaration_in_catalogs.py index 0551e2f..8b22c3e 100644 --- a/qc_openscenario/checks/parameters_checker/valid_parameter_declaration_in_catalogs.py +++ b/qc_openscenario/checks/parameters_checker/valid_parameter_declaration_in_catalogs.py @@ -6,10 +6,12 @@ from qc_openscenario import constants from qc_openscenario.checks import utils, models -from qc_openscenario.checks.parameters_checker import parameter_checker_precondition +from qc_openscenario import basic_preconditions CHECKER_ID = "check_asam_xosc_parameters_valid_parameter_declaration_in_catalogs" -MIN_RULE_VERSION = "1.2.0" +CHECKER_DESCRIPTION = "All parameters used within a catalog shall be declared within their ParameterDeclaration in the same catalog, which sets a default value for each parameter." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = "asam.net:xosc:1.2.0:parameters.valid_parameter_declaration_in_catalogs" def check_rule(checker_data: models.CheckerData) -> None: @@ -30,45 +32,6 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing valid_parameter_declaration_in_catalogs check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="All parameters used within a catalog shall be declared within their ParameterDeclaration in the same catalog, which sets a default value for each parameter.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="parameters.valid_parameter_declaration_in_catalogs", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - parameter_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - root = checker_data.input_file_xml_root catalogs_node = root.findall(".//Catalog") @@ -81,6 +44,12 @@ def check_rule(checker_data: models.CheckerData) -> None: status=StatusType.SKIPPED, ) + checker_data.result.add_checker_summary( + constants.BUNDLE_NAME, + CHECKER_ID, + "Cannot find Catalog nodes in provided XOSC file. Skip the check.", + ) + return logging.debug(f"catalogs_node : {catalogs_node}") @@ -127,9 +96,9 @@ def check_rule(checker_data: models.CheckerData) -> None: issue_id = checker_data.result.register_issue( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, - description="Issue flagging when used parameters is not defined or has not default value within a catalog", + description="Parameter not defined or without default value within a catalog", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, @@ -138,9 +107,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=xpath, description=f"Parameter value {attr_value[1:]} for attribute {attr_name} is not defined in Catalog or has no default value", ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/reference_checker/__init__.py b/qc_openscenario/checks/reference_checker/__init__.py index 335ceca..b3abddd 100644 --- a/qc_openscenario/checks/reference_checker/__init__.py +++ b/qc_openscenario/checks/reference_checker/__init__.py @@ -1,4 +1,3 @@ -from . import reference_checker as reference_checker from . import ( uniquely_resolvable_entity_references as uniquely_resolvable_entity_references, ) @@ -17,4 +16,3 @@ resolvable_storyboard_element_reference as resolvable_storyboard_element_reference, ) from . import unique_element_names_on_same_level as unique_element_names_on_same_level -from . import reference_checker_precondition as reference_checker_precondition diff --git a/qc_openscenario/checks/reference_checker/reference_checker.py b/qc_openscenario/checks/reference_checker/reference_checker.py deleted file mode 100644 index a73b42b..0000000 --- a/qc_openscenario/checks/reference_checker/reference_checker.py +++ /dev/null @@ -1,37 +0,0 @@ -import logging - - -from qc_baselib import StatusType - -from qc_openscenario import constants -from qc_openscenario.checks import models - -from qc_openscenario.checks.schema_checker import valid_schema - -from qc_openscenario.checks.reference_checker import ( - uniquely_resolvable_entity_references, - resolvable_signal_id_in_traffic_signal_state_action, - resolvable_traffic_signal_controller_by_traffic_signal_controller_ref, - valid_actor_reference_in_private_actions, - resolvable_entity_references, - resolvable_variable_reference, - resolvable_storyboard_element_reference, - unique_element_names_on_same_level, -) - - -def run_checks(checker_data: models.CheckerData) -> None: - logging.info("Executing reference checks") - - uniquely_resolvable_entity_references.check_rule(checker_data=checker_data) - resolvable_signal_id_in_traffic_signal_state_action.check_rule( - checker_data=checker_data - ) - resolvable_traffic_signal_controller_by_traffic_signal_controller_ref.check_rule( - checker_data=checker_data - ) - valid_actor_reference_in_private_actions.check_rule(checker_data=checker_data) - resolvable_entity_references.check_rule(checker_data=checker_data) - resolvable_variable_reference.check_rule(checker_data=checker_data) - resolvable_storyboard_element_reference.check_rule(checker_data=checker_data) - unique_element_names_on_same_level.check_rule(checker_data=checker_data) diff --git a/qc_openscenario/checks/reference_checker/resolvable_entity_references.py b/qc_openscenario/checks/reference_checker/resolvable_entity_references.py index 2fb82c6..a3e9009 100644 --- a/qc_openscenario/checks/reference_checker/resolvable_entity_references.py +++ b/qc_openscenario/checks/reference_checker/resolvable_entity_references.py @@ -4,11 +4,12 @@ from qc_openscenario import constants from qc_openscenario.checks import utils, models -from qc_openscenario.checks.reference_checker import reference_checker_precondition +from qc_openscenario import basic_preconditions CHECKER_ID = "check_asam_xosc_reference_control_resolvable_entity_references" -MIN_RULE_VERSION = "1.2.0" -RULE_SEVERITY = IssueSeverity.ERROR +CHECKER_DESCRIPTION = "A named reference in the EntityRef must be resolvable." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = "asam.net:xosc:1.2.0:reference_control.resolvable_entity_references" def check_rule(checker_data: models.CheckerData) -> None: @@ -28,56 +29,22 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing resolvable_entity_references check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="A named reference in the EntityRef must be resolvable.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="reference_control.resolvable_entity_references", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - reference_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - root = checker_data.input_file_xml_root entities_node = root.find("Entities") if entities_node is None: - logging.error("Cannot find Entities node in provided XOSC file. Skipping check") - checker_data.result.set_checker_status( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, status=StatusType.SKIPPED, ) + + checker_data.result.add_checker_summary( + constants.BUNDLE_NAME, + CHECKER_ID, + "Cannot find Entities node in provided XOSC file. Skip the check.", + ) + return defined_entities = set() @@ -89,15 +56,18 @@ def check_rule(checker_data: models.CheckerData) -> None: logging.debug(f"Defined entities : {defined_entities}") storyboard_node = root.find("Storyboard") if storyboard_node is None: - logging.error( - "Cannot find Storyboard node in provided XOSC file. Skipping check" - ) - checker_data.result.set_checker_status( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, status=StatusType.SKIPPED, ) + + checker_data.result.add_checker_summary( + constants.BUNDLE_NAME, + CHECKER_ID, + "Cannot find Storyboard node in provided XOSC file. Skip the check.", + ) + return nodes_with_entity_ref = storyboard_node.xpath(".//*[@entityRef]") @@ -135,9 +105,9 @@ def check_rule(checker_data: models.CheckerData) -> None: issue_id = checker_data.result.register_issue( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, - description="Issue flagging when an entity is referred in a entityRef attribute but it is not declared among Entities", - level=RULE_SEVERITY, - rule_uid=rule_uid, + description="Entity not declared among Entities but referred in an entityRef attribute", + level=IssueSeverity.ERROR, + rule_uid=RULE_UID, ) checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, @@ -146,9 +116,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=xpath, description=f"Entity at {xpath} with id {current_entity_ref} not found among defined Entities ", ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/reference_checker/resolvable_signal_id_in_traffic_signal_state_action.py b/qc_openscenario/checks/reference_checker/resolvable_signal_id_in_traffic_signal_state_action.py index 86fcdc5..273e97c 100644 --- a/qc_openscenario/checks/reference_checker/resolvable_signal_id_in_traffic_signal_state_action.py +++ b/qc_openscenario/checks/reference_checker/resolvable_signal_id_in_traffic_signal_state_action.py @@ -4,10 +4,12 @@ from qc_openscenario import constants from qc_openscenario.checks import utils, models -from qc_openscenario.checks.reference_checker import reference_checker_precondition +from qc_openscenario import basic_preconditions CHECKER_ID = "check_asam_xosc_reference_control_resolvable_signal_id_in_traffic_signal_state_action" -MIN_RULE_VERSION = "1.2.0" +CHECKER_DESCRIPTION = "TrafficSignalStateAction:name -> Signal ID must exist within the given road network." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = "asam.net:xosc:1.2.0:reference_control.resolvable_signal_id_in_traffic_signal_state_action" def check_rule(checker_data: models.CheckerData) -> None: @@ -27,65 +29,38 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing resolvable_signal_id_in_traffic_signal_state_action check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="TrafficSignalStateAction:name -> Signal ID must exist within the given road network.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="reference_control.resolvable_signal_id_in_traffic_signal_state_action", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - reference_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - root = checker_data.input_file_xml_root if checker_data.xodr_root is None: - logging.error(f" - Cannot read xodr file. Abort") checker_data.result.set_checker_status( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, status=StatusType.SKIPPED, ) + + checker_data.result.add_checker_summary( + constants.BUNDLE_NAME, + CHECKER_ID, + "Cannot read xodr file. Skip the check.", + ) + return xodr_signal_list = checker_data.xodr_root.findall(".//signal") if xodr_signal_list is None: - logging.error(f" - Cannot read signals from xodr file. Abort") checker_data.result.set_checker_status( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, status=StatusType.SKIPPED, ) + + checker_data.result.add_checker_summary( + constants.BUNDLE_NAME, + CHECKER_ID, + "Cannot read signals from xodr file. Skip the check.", + ) + return xodr_signal_ids = set() @@ -104,9 +79,9 @@ def check_rule(checker_data: models.CheckerData) -> None: issue_id = checker_data.result.register_issue( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, - description="Issue flagging traffic light id not present in linked xodr file", + description="Traffic light id not present in linked xodr file", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, @@ -115,9 +90,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=xpath, description=f"Traffic Light {xpath} with id {current_name} not found in xodr file", ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/reference_checker/resolvable_storyboard_element_reference.py b/qc_openscenario/checks/reference_checker/resolvable_storyboard_element_reference.py index 02178b6..1f857a1 100644 --- a/qc_openscenario/checks/reference_checker/resolvable_storyboard_element_reference.py +++ b/qc_openscenario/checks/reference_checker/resolvable_storyboard_element_reference.py @@ -5,10 +5,15 @@ from qc_openscenario import constants from qc_openscenario.checks import utils, models -from qc_openscenario.checks.reference_checker import reference_checker_precondition +from qc_openscenario import basic_preconditions CHECKER_ID = "check_asam_xosc_reference_control_resolvable_storyboard_element_reference" -MIN_RULE_VERSION = "1.2.0" +CHECKER_DESCRIPTION = "The attribute storyboardElementRef shall point to an existing element of the corresponding type and shall be uniquely resolvable." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = ( + "asam.net:xosc:1.2.0:reference_control.resolvable_storyboard_element_reference" +) + STORYBOARD_ELEMENTS = ["Act", "Action", "Event", "Maneuver", "ManeuverGroup", " Story"] @@ -30,70 +35,38 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing resolvable_storyboard_element_reference check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="The attribute storyboardElementRef shall point to an existing element of the corresponding type and shall be uniquely resolvable.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="reference_control.resolvable_storyboard_element_reference", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - reference_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - root = checker_data.input_file_xml_root storyboard_node = root.find("Storyboard") if storyboard_node is None: - logging.error( - "Cannot find Storyboard node in provided XOSC file. Skipping check" - ) checker_data.result.set_checker_status( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, status=StatusType.SKIPPED, ) + + checker_data.result.add_checker_summary( + constants.BUNDLE_NAME, + CHECKER_ID, + "Cannot find Storyboard node in the provided XOSC file. Skip the check.", + ) return xpath_expr = "|".join([f"//{node}" for node in STORYBOARD_ELEMENTS]) storyboard_elements = storyboard_node.xpath(xpath_expr) if storyboard_elements is None: - logging.error( - "Cannot find Storyboard elements node in provided XOSC file. Skipping check" - ) checker_data.result.set_checker_status( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, status=StatusType.SKIPPED, ) + + checker_data.result.add_checker_summary( + constants.BUNDLE_NAME, + CHECKER_ID, + "Cannot find Storyboard elements node in the provided XOSC file. Skip the check.", + ) + return storyboard_element_type = {} @@ -160,9 +133,9 @@ def check_rule(checker_data: models.CheckerData) -> None: issue_id = checker_data.result.register_issue( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, - description="Issue flagging when a storyboardElementRef does not point to an existing element", + description="Reference in a storyboardElementRef does not point to an existing element", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) issue_description = f"Storyboard element reference {current_storyboard_el_ref} not found among Storyboard elements " checker_data.result.add_xml_location( @@ -172,9 +145,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=xpath, description=issue_description, ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/reference_checker/resolvable_traffic_signal_controller_by_traffic_signal_controller_ref.py b/qc_openscenario/checks/reference_checker/resolvable_traffic_signal_controller_by_traffic_signal_controller_ref.py index de890d6..dfc4a4d 100644 --- a/qc_openscenario/checks/reference_checker/resolvable_traffic_signal_controller_by_traffic_signal_controller_ref.py +++ b/qc_openscenario/checks/reference_checker/resolvable_traffic_signal_controller_by_traffic_signal_controller_ref.py @@ -5,10 +5,12 @@ from qc_openscenario import constants from qc_openscenario.checks import utils, models -from qc_openscenario.checks.reference_checker import reference_checker_precondition +from qc_openscenario import basic_preconditions CHECKER_ID = "check_asam_xosc_reference_control_resolvable_traffic_signal_controller_by_traffic_signal_controller_ref" -MIN_RULE_VERSION = "1.2.0" +CHECKER_DESCRIPTION = "The trafficSignalController according to the trafficSignalControllerRef property must exist within the scenarios RoadNetwork definition." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = "asam.net:xosc:1.2.0:reference_control.resolvable_traffic_signal_controller_by_traffic_signal_controller_ref" def check_rule(checker_data: models.CheckerData) -> None: @@ -30,70 +32,39 @@ def check_rule(checker_data: models.CheckerData) -> None: "Executing resolvable_traffic_signal_controller_by_traffic_signal_controller_ref check" ) - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="The trafficSignalController according to the trafficSignalControllerRef property must exist within the scenarios RoadNetwork definition.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="reference_control.resolvable_traffic_signal_controller_by_traffic_signal_controller_ref", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - reference_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - root = checker_data.input_file_xml_root road_network = root.find("RoadNetwork") if road_network is None: - logging.error( - "Cannot find RoadNetwork node in provided XOSC file. Skipping check" - ) checker_data.result.set_checker_status( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, status=StatusType.SKIPPED, ) + + checker_data.result.add_checker_summary( + constants.BUNDLE_NAME, + CHECKER_ID, + "Cannot find RoadNetwork node. Skip the check.", + ) + return # ts = traffic signal ts_controllers = road_network.findall(".//TrafficSignalController") if ts_controllers is None: - logging.error( - "Cannot find TrafficSignalController nodes in RoadNetwork of provided XOSC file. Skipping check" - ) checker_data.result.set_checker_status( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, status=StatusType.SKIPPED, ) + + checker_data.result.add_checker_summary( + constants.BUNDLE_NAME, + CHECKER_ID, + "Cannot find TrafficSignalController nodes in RoadNetwork. Skip the check.", + ) + return ts_controller_names = set() @@ -112,9 +83,9 @@ def check_rule(checker_data: models.CheckerData) -> None: issue_id = checker_data.result.register_issue( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, - description="Issue flagging traffic signal controller reference not present in the declared RoadNetwork", + description="Traffic signal controller referred but not present in the declared RoadNetwork", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, @@ -123,9 +94,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=xpath, description=f"trafficSignalControllerRef at {xpath} with id {current_name} not found in RoadNetwork node", ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/reference_checker/resolvable_variable_reference.py b/qc_openscenario/checks/reference_checker/resolvable_variable_reference.py index 5abe2b5..cc01209 100644 --- a/qc_openscenario/checks/reference_checker/resolvable_variable_reference.py +++ b/qc_openscenario/checks/reference_checker/resolvable_variable_reference.py @@ -5,11 +5,12 @@ from qc_openscenario import constants from qc_openscenario.checks import utils, models -from qc_openscenario.checks.reference_checker import reference_checker_precondition +from qc_openscenario import basic_preconditions CHECKER_ID = "check_asam_xosc_reference_control_resolvable_variable_reference" -MIN_RULE_VERSION = "1.2.0" -RULE_SEVERITY = IssueSeverity.ERROR +CHECKER_DESCRIPTION = "The VariableDeclaration according to the variableRef property must exist within the ScenarioDefinition." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = "asam.net:xosc:1.2.0:reference_control.resolvable_variable_reference" def check_rule(checker_data: models.CheckerData) -> None: @@ -29,45 +30,6 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing resolvable_variable_reference check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="The VariableDeclaration according to the variableRef property must exist within the ScenarioDefinition.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="reference_control.resolvable_variable_reference", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - reference_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - root = checker_data.input_file_xml_root parameter_declaration_nodes = root.find("ParameterDeclarations") @@ -89,16 +51,18 @@ def check_rule(checker_data: models.CheckerData) -> None: storyboard_node = root.find("Storyboard") if storyboard_node is None: - logging.error( - "Cannot find Storyboard node in provided XOSC file. Skipping check" - ) - checker_data.result.set_checker_status( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, status=StatusType.SKIPPED, ) + checker_data.result.add_checker_summary( + constants.BUNDLE_NAME, + CHECKER_ID, + "Cannot find Storyboard node. Skip the check.", + ) + return nodes_with_variable_ref = storyboard_node.xpath(".//*[@variableRef]") @@ -111,9 +75,9 @@ def check_rule(checker_data: models.CheckerData) -> None: issue_id = checker_data.result.register_issue( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, - description="Issue flagging when a variable is referred in a variableRef attribute but it is not found within ScenarioDefinition", - level=RULE_SEVERITY, - rule_uid=rule_uid, + description="Variable not found within ScenarioDefinition but referred in a variableRef attribute", + level=IssueSeverity.ERROR, + rule_uid=RULE_UID, ) checker_data.result.add_xml_location( checker_bundle_name=constants.BUNDLE_NAME, @@ -122,9 +86,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=xpath, description=f"Variable with id {current_name} not found within ScenarioDefinition", ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/reference_checker/unique_element_names_on_same_level.py b/qc_openscenario/checks/reference_checker/unique_element_names_on_same_level.py index cd7073b..99a21e1 100644 --- a/qc_openscenario/checks/reference_checker/unique_element_names_on_same_level.py +++ b/qc_openscenario/checks/reference_checker/unique_element_names_on_same_level.py @@ -10,11 +10,13 @@ from qc_openscenario import constants from qc_openscenario.checks import utils, models -from qc_openscenario.checks.reference_checker import reference_checker_precondition +from qc_openscenario import basic_preconditions from collections import deque, defaultdict CHECKER_ID = "check_asam_xosc_reference_control_unique_element_names_on_same_level" -MIN_RULE_VERSION = "1.2.0" +CHECKER_DESCRIPTION = "Element names at each level shall be unique at that level." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = "asam.net:xosc:1.2.0:reference_control.unique_element_names_on_same_level" @dataclass @@ -79,45 +81,6 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing unique_element_names_on_same_level check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="Element names at each level shall be unique at that level.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="reference_control.unique_element_names_on_same_level", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - reference_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - tree = checker_data.input_file_xml_root duplicates_found = are_names_unique_at_each_level(tree, tree.getroot()) @@ -125,9 +88,9 @@ def check_rule(checker_data: models.CheckerData) -> None: issue_id = checker_data.result.register_issue( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, - description="Issue flagging when a element name is not unique within its level", + description="Duplicated element name used at given document level", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) issue_description = f"Element {duplicate.name} is duplicated" checker_data.result.add_xml_location( @@ -137,9 +100,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=duplicate.xpath, description=issue_description, ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/reference_checker/uniquely_resolvable_entity_references.py b/qc_openscenario/checks/reference_checker/uniquely_resolvable_entity_references.py index 141c4a4..907b053 100644 --- a/qc_openscenario/checks/reference_checker/uniquely_resolvable_entity_references.py +++ b/qc_openscenario/checks/reference_checker/uniquely_resolvable_entity_references.py @@ -4,15 +4,17 @@ from lxml import etree -from qc_baselib import IssueSeverity, StatusType +from qc_baselib import IssueSeverity from qc_openscenario import constants -from qc_openscenario.checks import utils, models -from qc_openscenario.checks.reference_checker import reference_checker_precondition +from qc_openscenario.checks import models +from qc_openscenario import basic_preconditions CHECKER_ID = "check_asam_xosc_reference_control_uniquely_resolvable_entity_references" -MIN_RULE_VERSION = "1.2.0" +CHECKER_DESCRIPTION = "Reference names must be unique" +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = "asam.net:xosc:1.2.0:reference_control.uniquely_resolvable_entity_references" def get_catalogs(root: etree._ElementTree) -> List[etree._ElementTree]: @@ -37,45 +39,6 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing uniquely_resolvable_entity_references check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="Input xml file must be valid according to the schema.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="reference_control.uniquely_resolvable_entity_references", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - reference_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - root = checker_data.input_file_xml_root # List to store problematic nodes @@ -111,9 +74,9 @@ def check_rule(checker_data: models.CheckerData) -> None: issue_id = checker_data.result.register_issue( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, - description="Referenced names are not unique", + description="Referenced entity name duplicated", level=IssueSeverity.WARNING, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) for error in errors: @@ -130,9 +93,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=error_duplicate_xpath, description=error_msg, ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/reference_checker/valid_actor_reference_in_private_actions.py b/qc_openscenario/checks/reference_checker/valid_actor_reference_in_private_actions.py index dc00851..e439379 100644 --- a/qc_openscenario/checks/reference_checker/valid_actor_reference_in_private_actions.py +++ b/qc_openscenario/checks/reference_checker/valid_actor_reference_in_private_actions.py @@ -4,14 +4,18 @@ from qc_baselib import IssueSeverity, StatusType from qc_openscenario import constants -from qc_openscenario.checks import utils, models +from qc_openscenario.checks import models -from qc_openscenario.checks.reference_checker import reference_checker_precondition +from qc_openscenario import basic_preconditions CHECKER_ID = ( "check_asam_xosc_reference_control_valid_actor_reference_in_private_actions" ) -MIN_RULE_VERSION = "1.2.0" +CHECKER_DESCRIPTION = "In a ManeuverGroup, if the defined action is a private action an actor must be defined." +CHECKER_PRECONDITIONS = basic_preconditions.CHECKER_PRECONDITIONS +RULE_UID = ( + "asam.net:xosc:1.2.0:reference_control.valid_actor_reference_in_private_actions" +) def check_rule(checker_data: models.CheckerData) -> None: @@ -32,57 +36,21 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing valid_actor_reference_in_private_actions check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="In a ManeuverGroup, if the defined action is a private action an actor must be defined.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting=MIN_RULE_VERSION, - rule_full_name="reference_control.valid_actor_reference_in_private_actions", - ) - - if not checker_data.result.all_checkers_completed_without_issue( - reference_checker_precondition.PRECONDITIONS - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - - schema_version = checker_data.schema_version - if ( - schema_version is None - or utils.compare_versions(schema_version, MIN_RULE_VERSION) < 0 - ): - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, - ) - - return - root = checker_data.input_file_xml_root maneuver_groups = root.findall(".//ManeuverGroup") if maneuver_groups is None: - logging.error( - "Cannot find ManeuverGroup node in provided XOSC file. Skipping check" - ) checker_data.result.set_checker_status( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, status=StatusType.SKIPPED, ) + + checker_data.result.add_checker_summary( + constants.BUNDLE_NAME, + CHECKER_ID, + "Cannot find ManeuverGroup node. Skip the check.", + ) return for maneuver_group in maneuver_groups: @@ -91,15 +59,18 @@ def check_rule(checker_data: models.CheckerData) -> None: entity_refs = maneuver_group.findall(".//EntityRef") if private_actions is None or entity_refs is None: - logging.error( - "Cannot find PrivateAction or EntityRef node in provided XOSC file. Skipping check" - ) - checker_data.result.set_checker_status( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, status=StatusType.SKIPPED, ) + + checker_data.result.add_checker_summary( + constants.BUNDLE_NAME, + CHECKER_ID, + "Cannot find PrivateAction or EntityRef node. Skip the check.", + ) + return has_private_action = len(private_actions) > 0 @@ -112,9 +83,9 @@ def check_rule(checker_data: models.CheckerData) -> None: issue_id = checker_data.result.register_issue( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, - description="Issue flagging when no Actor is specified but a PrivateAction is used", + description="No Actor is specified but a PrivateAction is used", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) private_actions_xpaths = [root.getpath(x) for x in private_actions] checker_data.result.add_xml_location( @@ -124,9 +95,3 @@ def check_rule(checker_data: models.CheckerData) -> None: xpath=xpath, description=f"ManeuverGroup at {xpath} uses private actions {private_actions_xpaths} but it defines no actor", ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/schema_checker/__init__.py b/qc_openscenario/checks/schema_checker/__init__.py index d643e74..660fc3a 100644 --- a/qc_openscenario/checks/schema_checker/__init__.py +++ b/qc_openscenario/checks/schema_checker/__init__.py @@ -1,2 +1 @@ -from . import schema_checker as schema_checker from . import valid_schema as valid_schema diff --git a/qc_openscenario/checks/schema_checker/schema_checker.py b/qc_openscenario/checks/schema_checker/schema_checker.py deleted file mode 100644 index 9ba0682..0000000 --- a/qc_openscenario/checks/schema_checker/schema_checker.py +++ /dev/null @@ -1,13 +0,0 @@ -import logging - - -from qc_openscenario.checks import models - -from qc_openscenario.checks.schema_checker import ( - valid_schema, -) - - -def run_checks(checker_data: models.CheckerData) -> None: - logging.info("Executing schema checks") - valid_schema.check_rule(checker_data) diff --git a/qc_openscenario/checks/schema_checker/valid_schema.py b/qc_openscenario/checks/schema_checker/valid_schema.py index 205ca7a..e3bf782 100644 --- a/qc_openscenario/checks/schema_checker/valid_schema.py +++ b/qc_openscenario/checks/schema_checker/valid_schema.py @@ -17,12 +17,14 @@ ) CHECKER_ID = "check_asam_xosc_xml_valid_schema" -PRECONDITIONS = { +CHECKER_DESCRIPTION = "Input xml file must be valid according to the schema." +CHECKER_PRECONDITIONS = { valid_xml_document.CHECKER_ID, root_tag_is_openscenario.CHECKER_ID, fileheader_is_present.CHECKER_ID, version_is_defined.CHECKER_ID, } +RULE_UID = "asam.net:xosc:1.0.0:xml.valid_schema" def _is_schema_compliant( @@ -62,45 +64,24 @@ def check_rule(checker_data: models.CheckerData) -> None: """ logging.info("Executing valid_schema check") - checker_data.result.register_checker( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - description="Input xml file must be valid according to the schema.", - ) - - rule_uid = checker_data.result.register_rule( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - emanating_entity="asam.net", - standard="xosc", - definition_setting="1.0.0", - rule_full_name="xml.valid_schema", - ) + schema_version = checker_data.schema_version + xsd_file = schema_files.SCHEMA_FILES.get(schema_version) - if not checker_data.result.all_checkers_completed_without_issue(PRECONDITIONS): + if xsd_file is None: checker_data.result.set_checker_status( checker_bundle_name=constants.BUNDLE_NAME, checker_id=CHECKER_ID, status=StatusType.SKIPPED, ) - return - - schema_version = checker_data.schema_version - if schema_version is None or schema_version not in schema_files.SCHEMA_FILES: - logging.info( - f"- Schema file for version {schema_version} does not exist. Skipping check" - ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.SKIPPED, + checker_data.result.add_checker_summary( + constants.BUNDLE_NAME, + CHECKER_ID, + f"- Schema file for version {schema_version} does not exist. Skip the check.", ) return - xsd_file = schema_files.SCHEMA_FILES[schema_version] xsd_file_path = str( importlib.resources.files("qc_openscenario.schema").joinpath(xsd_file) ) @@ -116,7 +97,7 @@ def check_rule(checker_data: models.CheckerData) -> None: checker_id=CHECKER_ID, description="Input file does not follow its version schema", level=IssueSeverity.ERROR, - rule_uid=rule_uid, + rule_uid=RULE_UID, ) checker_data.result.add_file_location( checker_bundle_name=constants.BUNDLE_NAME, @@ -126,9 +107,3 @@ def check_rule(checker_data: models.CheckerData) -> None: column=error.column, description=error.message, ) - - checker_data.result.set_checker_status( - checker_bundle_name=constants.BUNDLE_NAME, - checker_id=CHECKER_ID, - status=StatusType.COMPLETED, - ) diff --git a/qc_openscenario/checks/utils.py b/qc_openscenario/checks/utils.py index f9ba550..1bdb6e1 100644 --- a/qc_openscenario/checks/utils.py +++ b/qc_openscenario/checks/utils.py @@ -10,6 +10,13 @@ PARAMETER_PATTERN = re.compile(r"[$][A-Za-z_][A-Za-z0-9_]*") +def to_float(s): + try: + return float(s) + except (ValueError, TypeError): + return None + + def get_root_without_default_namespace(path: str) -> etree._ElementTree: with open(path, "rb") as raw_file: xml_string = raw_file.read().decode() diff --git a/qc_openscenario/main.py b/qc_openscenario/main.py index a6bd99a..3056511 100644 --- a/qc_openscenario/main.py +++ b/qc_openscenario/main.py @@ -1,16 +1,18 @@ import argparse import logging from datetime import datetime +import types -from qc_baselib import Configuration, Result +from qc_baselib import Configuration, Result, StatusType from qc_baselib.models.common import ParamType from qc_openscenario import constants -from qc_openscenario.checks.schema_checker import schema_checker -from qc_openscenario.checks.basic_checker import basic_checker -from qc_openscenario.checks.reference_checker import reference_checker -from qc_openscenario.checks.parameters_checker import parameters_checker -from qc_openscenario.checks.data_type_checker import data_type_checker +from qc_openscenario.checks import schema_checker +from qc_openscenario.checks import basic_checker +from qc_openscenario.checks import reference_checker +from qc_openscenario.checks import parameters_checker +from qc_openscenario.checks import data_type_checker +from qc_openscenario.checks import utils, models logging.basicConfig(format="%(asctime)s - %(message)s", level=logging.INFO) @@ -30,6 +32,194 @@ def args_entrypoint() -> argparse.Namespace: return parser.parse_args() +def execute_checker( + checker: types.ModuleType, + checker_data: models.CheckerData, + required_definition_setting: bool = True, +) -> None: + # Register checker + checker_data.result.register_checker( + checker_bundle_name=constants.BUNDLE_NAME, + checker_id=checker.CHECKER_ID, + description=checker.CHECKER_DESCRIPTION, + ) + + # Register rule uid + checker_data.result.register_rule_by_uid( + checker_bundle_name=constants.BUNDLE_NAME, + checker_id=checker.CHECKER_ID, + rule_uid=checker.RULE_UID, + ) + + # Check preconditions. If not satisfied then set status as SKIPPED and return + if not checker_data.result.all_checkers_completed_without_issue( + checker.CHECKER_PRECONDITIONS + ): + checker_data.result.set_checker_status( + checker_bundle_name=constants.BUNDLE_NAME, + checker_id=checker.CHECKER_ID, + status=StatusType.SKIPPED, + ) + + checker_data.result.add_checker_summary( + constants.BUNDLE_NAME, + checker.CHECKER_ID, + "Preconditions are not satisfied. Skip the check.", + ) + + return + + # Checker definition setting. If not satisfied then set status as SKIPPED and return + if required_definition_setting: + schema_version = checker_data.schema_version + + splitted_rule_uid = checker.RULE_UID.split(":") + if len(splitted_rule_uid) != 4: + raise RuntimeError(f"Invalid rule uid: {checker.RULE_UID}") + + definition_setting = splitted_rule_uid[2] + if ( + schema_version is None + or utils.compare_versions(schema_version, definition_setting) < 0 + ): + checker_data.result.set_checker_status( + checker_bundle_name=constants.BUNDLE_NAME, + checker_id=checker.CHECKER_ID, + status=StatusType.SKIPPED, + ) + + checker_data.result.add_checker_summary( + constants.BUNDLE_NAME, + checker.CHECKER_ID, + f"Version {schema_version} is lower than definition setting {definition_setting}. Skip the check.", + ) + + return + + # Execute checker + try: + checker.check_rule(checker_data) + + # If checker is not explicitly set as SKIPPED, then set it as COMPLETED + if ( + checker_data.result.get_checker_status(checker.CHECKER_ID) + != StatusType.SKIPPED + ): + checker_data.result.set_checker_status( + checker_bundle_name=constants.BUNDLE_NAME, + checker_id=checker.CHECKER_ID, + status=StatusType.COMPLETED, + ) + except Exception as e: + # If any exception occurs during the check, set the status as ERROR + checker_data.result.set_checker_status( + checker_bundle_name=constants.BUNDLE_NAME, + checker_id=checker.CHECKER_ID, + status=StatusType.ERROR, + ) + + checker_data.result.add_checker_summary( + constants.BUNDLE_NAME, checker.CHECKER_ID, f"Error: {str(e)}." + ) + + logging.exception(f"An error occurred in {checker.CHECKER_ID}.") + + +def run_checks(config: Configuration, result: Result) -> None: + checker_data = models.CheckerData( + xml_file_path=config.get_config_param("InputFile"), + input_file_xml_root=None, + config=config, + result=result, + schema_version=None, + xodr_root=None, + ) + + # 1. Run basic checks + execute_checker( + basic_checker.valid_xml_document, + checker_data, + required_definition_setting=False, + ) + + if result.all_checkers_completed_without_issue( + {basic_checker.valid_xml_document.CHECKER_ID} + ): + checker_data.input_file_xml_root = utils.get_root_without_default_namespace( + checker_data.xml_file_path + ) + + execute_checker( + basic_checker.root_tag_is_openscenario, + checker_data, + required_definition_setting=False, + ) + execute_checker( + basic_checker.fileheader_is_present, + checker_data, + required_definition_setting=False, + ) + execute_checker( + basic_checker.version_is_defined, + checker_data, + required_definition_setting=False, + ) + + # Get schema version and xodr road network if they exist + if result.all_checkers_completed_without_issue( + { + basic_checker.valid_xml_document.CHECKER_ID, + basic_checker.root_tag_is_openscenario.CHECKER_ID, + basic_checker.fileheader_is_present.CHECKER_ID, + basic_checker.version_is_defined.CHECKER_ID, + } + ): + checker_data.schema_version = utils.get_standard_schema_version( + checker_data.input_file_xml_root + ) + checker_data.xodr_root = utils.get_xodr_road_network( + checker_data.xml_file_path, checker_data.input_file_xml_root + ) + + # 2. Run schema check + execute_checker(schema_checker.valid_schema, checker_data) + + # 3. Run reference checks + execute_checker( + reference_checker.uniquely_resolvable_entity_references, checker_data + ) + execute_checker( + reference_checker.resolvable_signal_id_in_traffic_signal_state_action, + checker_data, + ) + execute_checker( + reference_checker.resolvable_traffic_signal_controller_by_traffic_signal_controller_ref, + checker_data, + ) + execute_checker( + reference_checker.valid_actor_reference_in_private_actions, checker_data + ) + execute_checker(reference_checker.resolvable_entity_references, checker_data) + execute_checker(reference_checker.resolvable_variable_reference, checker_data) + execute_checker( + reference_checker.resolvable_storyboard_element_reference, checker_data + ) + execute_checker(reference_checker.unique_element_names_on_same_level, checker_data) + + # 4. Run parameters checks + execute_checker( + parameters_checker.valid_parameter_declaration_in_catalogs, checker_data + ) + + # 5. Run data_type checks + execute_checker(data_type_checker.allowed_operators, checker_data) + execute_checker( + data_type_checker.non_negative_transition_time_in_light_state_action, + checker_data, + ) + execute_checker(data_type_checker.positive_duration_in_phase, checker_data) + + def main(): args = args_entrypoint() @@ -51,30 +241,15 @@ def main(): ) result.set_result_version(version=constants.BUNDLE_VERSION) - input_file_path = config.get_config_param("InputFile") - input_param = ParamType(name="InputFile", value=input_file_path) - result.get_checker_bundle_result(constants.BUNDLE_NAME).params.append( - input_param - ) - # 1. Run basic checks - checker_data = basic_checker.run_checks(config=config, result=result) - - # 2. Run xml checks - schema_checker.run_checks(checker_data) + run_checks(config, result) - # 3. Run reference checks - reference_checker.run_checks(checker_data) - - # 4. Run parameters checks - parameters_checker.run_checks(checker_data) - - # 5. Run data_type checks - data_type_checker.run_checks(checker_data) + result.copy_param_from_config(config) result.write_to_file( config.get_checker_bundle_param( checker_bundle_name=constants.BUNDLE_NAME, param_name="resultFile" - ) + ), + generate_summary=True, ) if args.generate_markdown: