From 2c9f93e084decb290f293cde1dfc70220fda27ff Mon Sep 17 00:00:00 2001 From: Brad Macdonald Date: Thu, 3 Aug 2023 09:52:04 -0600 Subject: [PATCH 01/30] updates repo for prototyping --- src/dcqc/suites/suite_abc.py | 5 ++++- src/dcqc/suites/suites.py | 6 +++--- src/dcqc/tests/base_test.py | 16 +++++++++++++++- src/dcqc/tests/grep_date_test.py | 7 +++++-- src/dcqc/updaters.py | 4 +++- 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/dcqc/suites/suite_abc.py b/src/dcqc/suites/suite_abc.py index 36a715d..4b4a8b2 100644 --- a/src/dcqc/suites/suite_abc.py +++ b/src/dcqc/suites/suite_abc.py @@ -19,7 +19,7 @@ class SuiteStatus(Enum): GREEN = "GREEN" # all tests passed RED = "RED" # one or more required tests failed AMBER = "AMBER" # all required tests passed, but one or more optional tests failed - # TODO GREY = "GREY" # error occurred + GREY = "GREY" # error occurred # TODO: Consider the Composite design pattern once @@ -225,6 +225,9 @@ def compute_status(self) -> SuiteStatus: for test in self.tests: test_name = test.type test_status = test.get_status() + if test_status == TestStatus.ERROR: + self._status = SuiteStatus.GREY + return self._status if test_name in self.required_tests: if test_status == TestStatus.FAIL: self._status = SuiteStatus.RED diff --git a/src/dcqc/suites/suites.py b/src/dcqc/suites/suites.py index dc28755..fb353fd 100644 --- a/src/dcqc/suites/suites.py +++ b/src/dcqc/suites/suites.py @@ -7,7 +7,7 @@ # to the file types class FileSuite(SuiteABC): file_type = FileType.get_file_type("*") - add_tests = (tests.FileExtensionTest, tests.Md5ChecksumTest) + # add_tests = (tests.FileExtensionTest, tests.Md5ChecksumTest) class JsonSuite(FileSuite): @@ -23,9 +23,9 @@ class JsonLdSuite(JsonSuite): class TiffSuite(FileSuite): file_type = FileType.get_file_type("TIFF") add_tests = ( - tests.LibTiffInfoTest, + # tests.LibTiffInfoTest, tests.GrepDateTest, - tests.TiffTag306DateTimeTest, + # tests.TiffTag306DateTimeTest, ) diff --git a/src/dcqc/tests/base_test.py b/src/dcqc/tests/base_test.py index fd1c610..f2b5817 100644 --- a/src/dcqc/tests/base_test.py +++ b/src/dcqc/tests/base_test.py @@ -22,6 +22,7 @@ class TestStatus(Enum): FAIL = "failed" PASS = "passed" SKIP = "skipped" + ERROR = "error" # TODO: Look into the @typing.final decorator @@ -73,6 +74,7 @@ def to_dict(self) -> SerializedObject: "tier": self.tier, "is_external_test": self.is_external_test, "status": self._status.value, + "reason": self.reason, "target": self.target.to_dict(), } return test_dict @@ -97,6 +99,8 @@ def from_dict(cls, dictionary: SerializedObject) -> BaseTest: status = TestStatus(dictionary["status"]) test._status = status + reason = dictionary["reason"] + test.reason = reason return test @@ -154,6 +158,10 @@ def from_dict(cls, dictionary: SerializedObject) -> Process: class ExternalTestMixin(BaseTest): pass_code: ClassVar[str] + fail_code: ClassVar[str] + reason: ClassVar[str] + reason_location: ClassVar[str] + # Class attributes is_external_test = True @@ -196,10 +204,16 @@ def _interpret_process_outputs(self, outputs: dict[str, Path]) -> TestStatus: """Interpret the process output files to yield a test status.""" exit_code = outputs["exit_code"].read_text() exit_code = exit_code.strip() + if exit_code == self.pass_code: status = TestStatus.PASS - else: + elif exit_code == self.fail_code: status = TestStatus.FAIL + # TODO: Include stdout and/or stderr in test json + self.reason = outputs[self.reason_location].read_text() + else: + status = TestStatus.ERROR + self.reason = outputs["std_err"].read_text() return status # TODO: Include process in serialized test dictionary diff --git a/src/dcqc/tests/grep_date_test.py b/src/dcqc/tests/grep_date_test.py index 668b94a..db40c63 100644 --- a/src/dcqc/tests/grep_date_test.py +++ b/src/dcqc/tests/grep_date_test.py @@ -5,6 +5,9 @@ class GrepDateTest(ExternalBaseTest): tier = 4 pass_code = "1" + fail_code = "0" + reason = "" + reason_location = "std_out" target: SingleTarget def generate_process(self) -> Process: @@ -15,9 +18,9 @@ def generate_process(self) -> Process: "-E", # extended regular expression "-i", # case insensitive "-a", # treat input as text - "-q", # suppress output + # "-q", # suppress output "'date|time'", # match date or time - f"'{path.name}'", + f"'abc.txt'", ] process = Process( container="quay.io/biocontainers/coreutils:8.30--h14c3975_1000", diff --git a/src/dcqc/updaters.py b/src/dcqc/updaters.py index 6002643..4233e92 100644 --- a/src/dcqc/updaters.py +++ b/src/dcqc/updaters.py @@ -29,7 +29,9 @@ def update(self, suites: List[SuiteABC]): # Evaluate dcqc_status for each url collapsed_dict = {} for url, statuses in suite_dict.items(): - if "RED" in statuses: + if "GREY" in statuses: + collapsed_dict[url] = "GREY" + elif "RED" in statuses: collapsed_dict[url] = "RED" elif "AMBER" in statuses: collapsed_dict[url] = "AMBER" From d188cf1ec8d0539dba4cb92f6653266de730a582 Mon Sep 17 00:00:00 2001 From: bwmac Date: Fri, 3 May 2024 11:23:00 -0600 Subject: [PATCH 02/30] updates for external test testing --- src/dcqc/suites/suites.py | 1 + src/dcqc/tests/base_test.py | 37 ++++++++++++++++++-------------- src/dcqc/tests/grep_date_test.py | 10 ++++----- src/docker/build.sh | 3 ++- 4 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/dcqc/suites/suites.py b/src/dcqc/suites/suites.py index 9575f21..8e2142b 100644 --- a/src/dcqc/suites/suites.py +++ b/src/dcqc/suites/suites.py @@ -49,6 +49,7 @@ class FastqSuite(FileSuite): class TXTSuite(FileSuite): file_type = FileType.get_file_type("TXT") + add_tests = tests.GrepDateTest class CSVSuite(FileSuite): diff --git a/src/dcqc/tests/base_test.py b/src/dcqc/tests/base_test.py index f2b5817..6ca88ed 100644 --- a/src/dcqc/tests/base_test.py +++ b/src/dcqc/tests/base_test.py @@ -41,13 +41,14 @@ class BaseTest(SerializableMixin, SubclassRegistryMixin, ABC, Generic[Target]): """ # Class attributes - tier: ClassVar[int] - is_external_test: ClassVar[bool] - is_external_test = False + tier: int + is_external_test: bool = False # Instance attributes type: str target: Target + failure_reason: str = "" + error_reason: str = "" def __init__(self, target: Target, skip: bool = False): self.type = self.__class__.__name__ @@ -74,7 +75,8 @@ def to_dict(self) -> SerializedObject: "tier": self.tier, "is_external_test": self.is_external_test, "status": self._status.value, - "reason": self.reason, + "failure_reason": self.failure_reason, + "error_reason": self.error_reason, "target": self.target.to_dict(), } return test_dict @@ -99,8 +101,8 @@ def from_dict(cls, dictionary: SerializedObject) -> BaseTest: status = TestStatus(dictionary["status"]) test._status = status - reason = dictionary["reason"] - test.reason = reason + test.failure_reason = dictionary["failure_reason"] + test.error_reason = dictionary["error_reason"] return test @@ -157,14 +159,18 @@ def from_dict(cls, dictionary: SerializedObject) -> Process: class ExternalTestMixin(BaseTest): - pass_code: ClassVar[str] - fail_code: ClassVar[str] - reason: ClassVar[str] - reason_location: ClassVar[str] - # Class attributes is_external_test = True + # Instance attributes + pass_code: int + fail_code: int + failure_reason_location: str + + process_exit_code: int + process_std_out: str + process_std_err: str + # Class constants STDOUT_PATH: ClassVar[Path] STDOUT_PATH = Path("std_out.txt") @@ -198,22 +204,21 @@ def _find_process_outputs( if not path.exists(): message = f"Expected process output ({path}) does not exist." raise FileNotFoundError(message) + return outputs def _interpret_process_outputs(self, outputs: dict[str, Path]) -> TestStatus: """Interpret the process output files to yield a test status.""" - exit_code = outputs["exit_code"].read_text() - exit_code = exit_code.strip() + exit_code = int(outputs["exit_code"].read_text().strip()) if exit_code == self.pass_code: status = TestStatus.PASS elif exit_code == self.fail_code: status = TestStatus.FAIL - # TODO: Include stdout and/or stderr in test json - self.reason = outputs[self.reason_location].read_text() + self.failure_reason = outputs[self.failure_reason_location].read_text() else: status = TestStatus.ERROR - self.reason = outputs["std_err"].read_text() + self.error_reason = outputs["std_err"].read_text() return status # TODO: Include process in serialized test dictionary diff --git a/src/dcqc/tests/grep_date_test.py b/src/dcqc/tests/grep_date_test.py index db40c63..13ef2da 100644 --- a/src/dcqc/tests/grep_date_test.py +++ b/src/dcqc/tests/grep_date_test.py @@ -4,10 +4,9 @@ class GrepDateTest(ExternalBaseTest): tier = 4 - pass_code = "1" - fail_code = "0" - reason = "" - reason_location = "std_out" + pass_code = 1 + fail_code = 0 + failure_reason_location = "std_out" target: SingleTarget def generate_process(self) -> Process: @@ -18,9 +17,8 @@ def generate_process(self) -> Process: "-E", # extended regular expression "-i", # case insensitive "-a", # treat input as text - # "-q", # suppress output "'date|time'", # match date or time - f"'abc.txt'", + f"'{path.name}'", ] process = Process( container="quay.io/biocontainers/coreutils:8.30--h14c3975_1000", diff --git a/src/docker/build.sh b/src/docker/build.sh index 8f77a3a..2d6f0cd 100644 --- a/src/docker/build.sh +++ b/src/docker/build.sh @@ -8,7 +8,8 @@ TARBALL_PATH=$(ls dist/*.tar.gz) export TARBALL_PATH docker build \ - -t dcqc \ + -t bwmac03570/dcqc \ -f "${SCRIPT_DIR}/Dockerfile" \ + --platform linux/amd64 \ --build-arg TARBALL_PATH \ "${SCRIPT_DIR}/../.." From 13a36fb691d0253508f4fdd854c372380df00ce1 Mon Sep 17 00:00:00 2001 From: bwmac Date: Fri, 3 May 2024 11:35:59 -0600 Subject: [PATCH 03/30] fix test tuple --- src/dcqc/suites/suites.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dcqc/suites/suites.py b/src/dcqc/suites/suites.py index 8e2142b..437b2ca 100644 --- a/src/dcqc/suites/suites.py +++ b/src/dcqc/suites/suites.py @@ -49,7 +49,7 @@ class FastqSuite(FileSuite): class TXTSuite(FileSuite): file_type = FileType.get_file_type("TXT") - add_tests = tests.GrepDateTest + add_tests = (tests.GrepDateTest,) class CSVSuite(FileSuite): From 49b5b100f0eb55949a6542d7840eb81e667b690e Mon Sep 17 00:00:00 2001 From: bwmac Date: Mon, 6 May 2024 09:43:22 -0600 Subject: [PATCH 04/30] bump fs-synapse version --- Pipfile.lock | 1266 ++++++++++++++++++++++++++++---------------------- setup.cfg | 2 +- 2 files changed, 711 insertions(+), 557 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index c9ad561..4691db5 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -23,13 +23,21 @@ ], "version": "==1.4.4" }, + "backoff": { + "hashes": [ + "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba", + "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8" + ], + "markers": "python_version >= '3.7'", + "version": "==2.2.1" + }, "certifi": { "hashes": [ - "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1", - "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474" + "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f", + "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1" ], "markers": "python_version >= '3.6'", - "version": "==2023.11.17" + "version": "==2024.2.2" }, "charset-normalizer": { "hashes": [ @@ -159,27 +167,35 @@ }, "fs-synapse": { "hashes": [ - "sha256:1c8fb5b1da3220d21d13a6e48642d8b75a913a9b4779b99d6de9fc6074167898", - "sha256:8d95badbd14a052eac06875bcefec4570d336bbe318f0aa7878c469a70dfd35f" + "sha256:3fe1397564b0a84e4f6ae9e07bf3a0d002623d486e591a965a89be4b3e392bf4", + "sha256:c4ec5c3d04d7fcc3a4115cdf496e1055a680893a2dfb1c649271fc240964efe9" ], - "markers": "python_version >= '3.8'", - "version": "==1.0.0" + "markers": "python_version < '3.12' and python_version >= '3.9'", + "version": "==2.0.1" + }, + "googleapis-common-protos": { + "hashes": [ + "sha256:17ad01b11d5f1d0171c06d3ba5c04c54474e883b66b949722b4938ee2694ef4e", + "sha256:ae45f75702f7c08b541f750854a678bd8f534a1a6bace6afe975f1d0a82d6632" + ], + "markers": "python_version >= '3.7'", + "version": "==1.63.0" }, "idna": { "hashes": [ - "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca", - "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f" + "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc", + "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0" ], "markers": "python_version >= '3.5'", - "version": "==3.6" + "version": "==3.7" }, "importlib-metadata": { "hashes": [ - "sha256:8a8a81bcf996e74fee46f0d16bd3eaa382a7eb20fd82445c3ad11f4090334116", - "sha256:dd0173e8f150d6815e098fd354f6414b0f079af4644ddfe90c71e2fc6174346d" + "sha256:1231cf92d825c9e03cfc4da076a16de6422c863558229ea0b22b675657463443", + "sha256:f0afba6205ad8f8947c7d338b5342d5db2afbfd82f9cbef7879a9539cc12eb9b" ], - "markers": "python_version >= '3.7'", - "version": "==4.13.0" + "markers": "python_version >= '3.8'", + "version": "==6.11.0" }, "isodate": { "hashes": [ @@ -188,21 +204,86 @@ ], "version": "==0.6.1" }, - "keyring": { + "nest-asyncio": { "hashes": [ - "sha256:17e49fb0d6883c2b4445359434dba95aad84aabb29bbff044ad0ed7100232eca", - "sha256:89cbd74d4683ed164c8082fb38619341097741323b3786905c6dac04d6915a55" + "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", + "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c" ], - "markers": "python_version >= '3.6'", - "version": "==23.4.1" + "markers": "python_version >= '3.5'", + "version": "==1.6.0" + }, + "opentelemetry-api": { + "hashes": [ + "sha256:4bb86b28627b7e41098f0e93280fe4892a1abed1b79a19aec6f928f39b17dffb", + "sha256:d6185fd5043e000075d921822fd2d26b953eba8ca21b1e2fa360dd46a7686316" + ], + "markers": "python_version >= '3.7'", + "version": "==1.21.0" + }, + "opentelemetry-exporter-otlp-proto-common": { + "hashes": [ + "sha256:61db274d8a68d636fb2ec2a0f281922949361cdd8236e25ff5539edf942b3226", + "sha256:97b1022b38270ec65d11fbfa348e0cd49d12006485c2321ea3b1b7037d42b6ec" + ], + "markers": "python_version >= '3.7'", + "version": "==1.21.0" + }, + "opentelemetry-exporter-otlp-proto-http": { + "hashes": [ + "sha256:19d60afa4ae8597f7ef61ad75c8b6c6b7ef8cb73a33fb4aed4dbc86d5c8d3301", + "sha256:56837773de6fb2714c01fc4895caebe876f6397bbc4d16afddf89e1299a55ee2" + ], + "markers": "python_version >= '3.7'", + "version": "==1.21.0" + }, + "opentelemetry-proto": { + "hashes": [ + "sha256:32fc4248e83eebd80994e13963e683f25f3b443226336bb12b5b6d53638f50ba", + "sha256:7d5172c29ed1b525b5ecf4ebe758c7138a9224441b3cfe683d0a237c33b1941f" + ], + "markers": "python_version >= '3.7'", + "version": "==1.21.0" + }, + "opentelemetry-sdk": { + "hashes": [ + "sha256:3ec8cd3020328d6bc5c9991ccaf9ae820ccb6395a5648d9a95d3ec88275b8879", + "sha256:9fe633243a8c655fedace3a0b89ccdfc654c0290ea2d8e839bd5db3131186f73" + ], + "markers": "python_version >= '3.7'", + "version": "==1.21.0" + }, + "opentelemetry-semantic-conventions": { + "hashes": [ + "sha256:44ae67a0a3252a05072877857e5cc1242c98d4cf12870159f1a94bec800d38ec", + "sha256:5cd719cbfec448af658860796c5d0fcea2fdf0945a2bed2363f42cb1ee39f526" + ], + "markers": "python_version >= '3.7'", + "version": "==0.42b0" + }, + "protobuf": { + "hashes": [ + "sha256:19b270aeaa0099f16d3ca02628546b8baefe2955bbe23224aaf856134eccf1e4", + "sha256:209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8", + "sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c", + "sha256:7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d", + "sha256:c053062984e61144385022e53678fbded7aea14ebb3e0305ae3592fb219ccfa4", + "sha256:d4198877797a83cbfe9bffa3803602bbe1625dc30d8a097365dbc762e5790faa", + "sha256:e3c97a1555fd6388f857770ff8b9703083de6bf1f9274a002a332d65fbb56c8c", + "sha256:e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019", + "sha256:f0700d54bcf45424477e46a9f0944155b46fb0639d69728739c0e47bab83f2b9", + "sha256:f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c", + "sha256:f4f118245c4a087776e0a8408be33cf09f6c547442c00395fbfb116fac2f8ac2" + ], + "markers": "python_version >= '3.8'", + "version": "==4.25.3" }, "pyparsing": { "hashes": [ - "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb", - "sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db" + "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad", + "sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742" ], "markers": "python_full_version >= '3.6.8'", - "version": "==3.1.1" + "version": "==3.1.2" }, "rdflib": { "hashes": [ @@ -221,11 +302,11 @@ }, "setuptools": { "hashes": [ - "sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2", - "sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6" + "sha256:6c1fccdac05a97e598fb0ae3bbed5904ccb317337a51139dcd51453611bbb987", + "sha256:c636ac361bc47580504644275c9ad802c50415c7522212252c033bd15f301f32" ], "markers": "python_version >= '3.8'", - "version": "==69.0.2" + "version": "==69.5.1" }, "six": { "hashes": [ @@ -237,11 +318,11 @@ }, "synapseclient": { "hashes": [ - "sha256:dc5a61f9f495109a0c89aa7d42b641b6ff278280d7961fb450dd5015704fe15b", - "sha256:dd8b1a1b4667d08311bb651469431f43fe2eeab83c0ef1fe5a03c2929aeb26cd" + "sha256:5261a2751ea5757750e0cb2e481ecb2761954e2c0969e7cc5dd1dfff43c3ddcc", + "sha256:c5e0ac45faed1aa618cd66a0f50bf1a8149a2902a71d07487a0e470250955083" ], - "markers": "python_version >= '3.7'", - "version": "==2.7.2" + "markers": "python_version >= '3.8'", + "version": "==4.1.1" }, "typer": { "hashes": [ @@ -251,6 +332,14 @@ "markers": "python_version >= '3.6'", "version": "==0.7.0" }, + "typing-extensions": { + "hashes": [ + "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0", + "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a" + ], + "markers": "python_version >= '3.8'", + "version": "==4.11.0" + }, "urllib3": { "hashes": [ "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07", @@ -337,21 +426,21 @@ }, "zipp": { "hashes": [ - "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31", - "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0" + "sha256:206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b", + "sha256:2884ed22e7d8961de1c9a05142eb69a247f120291bc0206a00a7642f09b5b715" ], "markers": "python_version >= '3.8'", - "version": "==3.17.0" + "version": "==3.18.1" } }, "develop": { "alabaster": { "hashes": [ - "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3", - "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2" + "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65", + "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92" ], - "markers": "python_version >= '3.6'", - "version": "==0.7.13" + "markers": "python_version >= '3.9'", + "version": "==0.7.16" }, "appdirs": { "hashes": [ @@ -362,11 +451,11 @@ }, "appnope": { "hashes": [ - "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24", - "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e" + "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee", + "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c" ], "markers": "platform_system == 'Darwin'", - "version": "==0.1.3" + "version": "==0.1.4" }, "asttokens": { "hashes": [ @@ -377,19 +466,27 @@ }, "attrs": { "hashes": [ - "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04", - "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015" + "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30", + "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1" ], "markers": "python_version >= '3.7'", - "version": "==23.1.0" + "version": "==23.2.0" }, "babel": { "hashes": [ - "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363", - "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287" + "sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb", + "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413" + ], + "markers": "python_version >= '3.8'", + "version": "==2.15.0" + }, + "backoff": { + "hashes": [ + "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba", + "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8" ], "markers": "python_version >= '3.7'", - "version": "==2.14.0" + "version": "==2.2.1" }, "black": { "hashes": [ @@ -410,11 +507,11 @@ }, "certifi": { "hashes": [ - "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1", - "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474" + "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f", + "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1" ], "markers": "python_version >= '3.6'", - "version": "==2023.11.17" + "version": "==2024.2.2" }, "cfgv": { "hashes": [ @@ -538,72 +635,72 @@ }, "comm": { "hashes": [ - "sha256:2da8d9ebb8dd7bfc247adaff99f24dce705638a8042b85cb995066793e391001", - "sha256:a517ea2ca28931c7007a7a99c562a0fa5883cfb48963140cf642c41c948498be" + "sha256:3fd7a84065306e07bea1773df6eb8282de51ba82f77c72f9c85716ab11fe980e", + "sha256:e6fb86cb70ff661ee8c9c14e7d36d6de3b4066f1441be4063df9c5009f0a64d3" ], "markers": "python_version >= '3.8'", - "version": "==0.2.0" + "version": "==0.2.2" }, "coverage": { "extras": [ "toml" ], "hashes": [ - "sha256:0cbf38419fb1a347aaf63481c00f0bdc86889d9fbf3f25109cf96c26b403fda1", - "sha256:12d15ab5833a997716d76f2ac1e4b4d536814fc213c85ca72756c19e5a6b3d63", - "sha256:149de1d2401ae4655c436a3dced6dd153f4c3309f599c3d4bd97ab172eaf02d9", - "sha256:1981f785239e4e39e6444c63a98da3a1db8e971cb9ceb50a945ba6296b43f312", - "sha256:2443cbda35df0d35dcfb9bf8f3c02c57c1d6111169e3c85fc1fcc05e0c9f39a3", - "sha256:289fe43bf45a575e3ab10b26d7b6f2ddb9ee2dba447499f5401cfb5ecb8196bb", - "sha256:2f11cc3c967a09d3695d2a6f03fb3e6236622b93be7a4b5dc09166a861be6d25", - "sha256:307adb8bd3abe389a471e649038a71b4eb13bfd6b7dd9a129fa856f5c695cf92", - "sha256:310b3bb9c91ea66d59c53fa4989f57d2436e08f18fb2f421a1b0b6b8cc7fffda", - "sha256:315a989e861031334d7bee1f9113c8770472db2ac484e5b8c3173428360a9148", - "sha256:3a4006916aa6fee7cd38db3bfc95aa9c54ebb4ffbfc47c677c8bba949ceba0a6", - "sha256:3c7bba973ebee5e56fe9251300c00f1579652587a9f4a5ed8404b15a0471f216", - "sha256:4175e10cc8dda0265653e8714b3174430b07c1dca8957f4966cbd6c2b1b8065a", - "sha256:43668cabd5ca8258f5954f27a3aaf78757e6acf13c17604d89648ecc0cc66640", - "sha256:4cbae1051ab791debecc4a5dcc4a1ff45fc27b91b9aee165c8a27514dd160836", - "sha256:5c913b556a116b8d5f6ef834038ba983834d887d82187c8f73dec21049abd65c", - "sha256:5f7363d3b6a1119ef05015959ca24a9afc0ea8a02c687fe7e2d557705375c01f", - "sha256:630b13e3036e13c7adc480ca42fa7afc2a5d938081d28e20903cf7fd687872e2", - "sha256:72c0cfa5250f483181e677ebc97133ea1ab3eb68645e494775deb6a7f6f83901", - "sha256:7dbc3ed60e8659bc59b6b304b43ff9c3ed858da2839c78b804973f613d3e92ed", - "sha256:88ed2c30a49ea81ea3b7f172e0269c182a44c236eb394718f976239892c0a27a", - "sha256:89a937174104339e3a3ffcf9f446c00e3a806c28b1841c63edb2b369310fd074", - "sha256:9028a3871280110d6e1aa2df1afd5ef003bab5fb1ef421d6dc748ae1c8ef2ebc", - "sha256:99b89d9f76070237975b315b3d5f4d6956ae354a4c92ac2388a5695516e47c84", - "sha256:9f805d62aec8eb92bab5b61c0f07329275b6f41c97d80e847b03eb894f38d083", - "sha256:a889ae02f43aa45032afe364c8ae84ad3c54828c2faa44f3bfcafecb5c96b02f", - "sha256:aa72dbaf2c2068404b9870d93436e6d23addd8bbe9295f49cbca83f6e278179c", - "sha256:ac8c802fa29843a72d32ec56d0ca792ad15a302b28ca6203389afe21f8fa062c", - "sha256:ae97af89f0fbf373400970c0a21eef5aa941ffeed90aee43650b81f7d7f47637", - "sha256:af3d828d2c1cbae52d34bdbb22fcd94d1ce715d95f1a012354a75e5913f1bda2", - "sha256:b4275802d16882cf9c8b3d057a0839acb07ee9379fa2749eca54efbce1535b82", - "sha256:b4767da59464bb593c07afceaddea61b154136300881844768037fd5e859353f", - "sha256:b631c92dfe601adf8f5ebc7fc13ced6bb6e9609b19d9a8cd59fa47c4186ad1ce", - "sha256:be32ad29341b0170e795ca590e1c07e81fc061cb5b10c74ce7203491484404ef", - "sha256:beaa5c1b4777f03fc63dfd2a6bd820f73f036bfb10e925fce067b00a340d0f3f", - "sha256:c0ba320de3fb8c6ec16e0be17ee1d3d69adcda99406c43c0409cb5c41788a611", - "sha256:c9eacf273e885b02a0273bb3a2170f30e2d53a6d53b72dbe02d6701b5296101c", - "sha256:cb536f0dcd14149425996821a168f6e269d7dcd2c273a8bff8201e79f5104e76", - "sha256:d1bc430677773397f64a5c88cb522ea43175ff16f8bfcc89d467d974cb2274f9", - "sha256:d1c88ec1a7ff4ebca0219f5b1ef863451d828cccf889c173e1253aa84b1e07ce", - "sha256:d3d9df4051c4a7d13036524b66ecf7a7537d14c18a384043f30a303b146164e9", - "sha256:d51ac2a26f71da1b57f2dc81d0e108b6ab177e7d30e774db90675467c847bbdf", - "sha256:d872145f3a3231a5f20fd48500274d7df222e291d90baa2026cc5152b7ce86bf", - "sha256:d8f17966e861ff97305e0801134e69db33b143bbfb36436efb9cfff6ec7b2fd9", - "sha256:dbc1b46b92186cc8074fee9d9fbb97a9dd06c6cbbef391c2f59d80eabdf0faa6", - "sha256:e10c39c0452bf6e694511c901426d6b5ac005acc0f78ff265dbe36bf81f808a2", - "sha256:e267e9e2b574a176ddb983399dec325a80dbe161f1a32715c780b5d14b5f583a", - "sha256:f47d39359e2c3779c5331fc740cf4bce6d9d680a7b4b4ead97056a0ae07cb49a", - "sha256:f6e9589bd04d0461a417562649522575d8752904d35c12907d8c9dfeba588faf", - "sha256:f94b734214ea6a36fe16e96a70d941af80ff3bfd716c141300d95ebc85339738", - "sha256:fa28e909776dc69efb6ed975a63691bc8172b64ff357e663a1bb06ff3c9b589a", - "sha256:fe494faa90ce6381770746077243231e0b83ff3f17069d748f645617cefe19d4" + "sha256:0646599e9b139988b63704d704af8e8df7fa4cbc4a1f33df69d97f36cb0a38de", + "sha256:0cdcbc320b14c3e5877ee79e649677cb7d89ef588852e9583e6b24c2e5072661", + "sha256:0d0a0f5e06881ecedfe6f3dd2f56dcb057b6dbeb3327fd32d4b12854df36bf26", + "sha256:1434e088b41594baa71188a17533083eabf5609e8e72f16ce8c186001e6b8c41", + "sha256:16db7f26000a07efcf6aea00316f6ac57e7d9a96501e990a36f40c965ec7a95d", + "sha256:1cc0fe9b0b3a8364093c53b0b4c0c2dd4bb23acbec4c9240b5f284095ccf7981", + "sha256:1fc81d5878cd6274ce971e0a3a18a8803c3fe25457165314271cf78e3aae3aa2", + "sha256:2ec92012fefebee89a6b9c79bc39051a6cb3891d562b9270ab10ecfdadbc0c34", + "sha256:39afcd3d4339329c5f58de48a52f6e4e50f6578dd6099961cf22228feb25f38f", + "sha256:4a7b0ceee8147444347da6a66be737c9d78f3353b0681715b668b72e79203e4a", + "sha256:4a9ca3f2fae0088c3c71d743d85404cec8df9be818a005ea065495bedc33da35", + "sha256:4bf0655ab60d754491004a5efd7f9cccefcc1081a74c9ef2da4735d6ee4a6223", + "sha256:4cc37def103a2725bc672f84bd939a6fe4522310503207aae4d56351644682f1", + "sha256:4fc84a37bfd98db31beae3c2748811a3fa72bf2007ff7902f68746d9757f3746", + "sha256:5037f8fcc2a95b1f0e80585bd9d1ec31068a9bcb157d9750a172836e98bc7a90", + "sha256:54de9ef3a9da981f7af93eafde4ede199e0846cd819eb27c88e2b712aae9708c", + "sha256:556cf1a7cbc8028cb60e1ff0be806be2eded2daf8129b8811c63e2b9a6c43bca", + "sha256:57e0204b5b745594e5bc14b9b50006da722827f0b8c776949f1135677e88d0b8", + "sha256:5a5740d1fb60ddf268a3811bcd353de34eb56dc24e8f52a7f05ee513b2d4f596", + "sha256:5c3721c2c9e4c4953a41a26c14f4cef64330392a6d2d675c8b1db3b645e31f0e", + "sha256:5fa567e99765fe98f4e7d7394ce623e794d7cabb170f2ca2ac5a4174437e90dd", + "sha256:5fd215c0c7d7aab005221608a3c2b46f58c0285a819565887ee0b718c052aa4e", + "sha256:6175d1a0559986c6ee3f7fccfc4a90ecd12ba0a383dcc2da30c2b9918d67d8a3", + "sha256:61c4bf1ba021817de12b813338c9be9f0ad5b1e781b9b340a6d29fc13e7c1b5e", + "sha256:6537e7c10cc47c595828b8a8be04c72144725c383c4702703ff4e42e44577312", + "sha256:68f962d9b72ce69ea8621f57551b2fa9c70509af757ee3b8105d4f51b92b41a7", + "sha256:7352b9161b33fd0b643ccd1f21f3a3908daaddf414f1c6cb9d3a2fd618bf2572", + "sha256:796a79f63eca8814ca3317a1ea443645c9ff0d18b188de470ed7ccd45ae79428", + "sha256:79afb6197e2f7f60c4824dd4b2d4c2ec5801ceb6ba9ce5d2c3080e5660d51a4f", + "sha256:7a588d39e0925f6a2bff87154752481273cdb1736270642aeb3635cb9b4cad07", + "sha256:8748731ad392d736cc9ccac03c9845b13bb07d020a33423fa5b3a36521ac6e4e", + "sha256:8fe7502616b67b234482c3ce276ff26f39ffe88adca2acf0261df4b8454668b4", + "sha256:9314d5678dcc665330df5b69c1e726a0e49b27df0461c08ca12674bcc19ef136", + "sha256:9735317685ba6ec7e3754798c8871c2f49aa5e687cc794a0b1d284b2389d1bd5", + "sha256:9981706d300c18d8b220995ad22627647be11a4276721c10911e0e9fa44c83e8", + "sha256:9e78295f4144f9dacfed4f92935fbe1780021247c2fabf73a819b17f0ccfff8d", + "sha256:b016ea6b959d3b9556cb401c55a37547135a587db0115635a443b2ce8f1c7228", + "sha256:b6cf3764c030e5338e7f61f95bd21147963cf6aa16e09d2f74f1fa52013c1206", + "sha256:beccf7b8a10b09c4ae543582c1319c6df47d78fd732f854ac68d518ee1fb97fa", + "sha256:c0884920835a033b78d1c73b6d3bbcda8161a900f38a488829a83982925f6c2e", + "sha256:c3e757949f268364b96ca894b4c342b41dc6f8f8b66c37878aacef5930db61be", + "sha256:ca498687ca46a62ae590253fba634a1fe9836bc56f626852fb2720f334c9e4e5", + "sha256:d1d0d98d95dd18fe29dc66808e1accf59f037d5716f86a501fc0256455219668", + "sha256:d21918e9ef11edf36764b93101e2ae8cc82aa5efdc7c5a4e9c6c35a48496d601", + "sha256:d7fed867ee50edf1a0b4a11e8e5d0895150e572af1cd6d315d557758bfa9c057", + "sha256:db66fc317a046556a96b453a58eced5024af4582a8dbdc0c23ca4dbc0d5b3146", + "sha256:dde0070c40ea8bb3641e811c1cfbf18e265d024deff6de52c5950677a8fb1e0f", + "sha256:df4e745a81c110e7446b1cc8131bf986157770fa405fe90e15e850aaf7619bc8", + "sha256:e2213def81a50519d7cc56ed643c9e93e0247f5bbe0d1247d15fa520814a7cd7", + "sha256:ef48e2707fb320c8f139424a596f5b69955a85b178f15af261bab871873bb987", + "sha256:f152cbf5b88aaeb836127d920dd0f5e7edff5a66f10c079157306c4343d86c19", + "sha256:fc0b4d8bfeabd25ea75e94632f5b6e047eef8adaed0c2161ada1e922e7f7cece" ], "markers": "python_version >= '3.8'", - "version": "==7.3.2" + "version": "==7.5.1" }, "dcqc": { "editable": true, @@ -614,27 +711,31 @@ }, "debugpy": { "hashes": [ - "sha256:125b9a637e013f9faac0a3d6a82bd17c8b5d2c875fb6b7e2772c5aba6d082332", - "sha256:12af2c55b419521e33d5fb21bd022df0b5eb267c3e178f1d374a63a2a6bdccd0", - "sha256:3c6fb41c98ec51dd010d7ed650accfd07a87fe5e93eca9d5f584d0578f28f35f", - "sha256:46ab6780159eeabb43c1495d9c84cf85d62975e48b6ec21ee10c95767c0590aa", - "sha256:57161629133113c97b387382045649a2b985a348f0c9366e22217c87b68b73c6", - "sha256:5d9de202f5d42e62f932507ee8b21e30d49aae7e46d5b1dd5c908db1d7068637", - "sha256:60009b132c91951354f54363f8ebdf7457aeb150e84abba5ae251b8e9f29a8a6", - "sha256:61eab4a4c8b6125d41a34bad4e5fe3d2cc145caecd63c3fe953be4cc53e65bf8", - "sha256:7fb95ca78f7ac43393cd0e0f2b6deda438ec7c5e47fa5d38553340897d2fbdfb", - "sha256:8cd0197141eb9e8a4566794550cfdcdb8b3db0818bdf8c49a8e8f8053e56e38b", - "sha256:9c9b0ac1ce2a42888199df1a1906e45e6f3c9555497643a85e0bf2406e3ffbc4", - "sha256:a64093656c4c64dc6a438e11d59369875d200bd5abb8f9b26c1f5f723622e153", - "sha256:a8b7a2fd27cd9f3553ac112f356ad4ca93338feadd8910277aff71ab24d8775f", - "sha256:b05a6b503ed520ad58c8dc682749113d2fd9f41ffd45daec16e558ca884008cd", - "sha256:bdc5ef99d14b9c0fcb35351b4fbfc06ac0ee576aeab6b2511702e5a648a2e595", - "sha256:e3412f9faa9ade82aa64a50b602544efcba848c91384e9f93497a458767e6926", - "sha256:ef54404365fae8d45cf450d0544ee40cefbcb9cb85ea7afe89a963c27028261e", - "sha256:ef9ab7df0b9a42ed9c878afd3eaaff471fce3fa73df96022e1f5c9f8f8c87ada" + "sha256:016a9fcfc2c6b57f939673c874310d8581d51a0fe0858e7fac4e240c5eb743cb", + "sha256:0de56aba8249c28a300bdb0672a9b94785074eb82eb672db66c8144fff673146", + "sha256:1a9fe0829c2b854757b4fd0a338d93bc17249a3bf69ecf765c61d4c522bb92a8", + "sha256:28acbe2241222b87e255260c76741e1fbf04fdc3b6d094fcf57b6c6f75ce1242", + "sha256:3a79c6f62adef994b2dbe9fc2cc9cc3864a23575b6e387339ab739873bea53d0", + "sha256:3bda0f1e943d386cc7a0e71bfa59f4137909e2ed947fb3946c506e113000f741", + "sha256:3ebb70ba1a6524d19fa7bb122f44b74170c447d5746a503e36adc244a20ac539", + "sha256:58911e8521ca0c785ac7a0539f1e77e0ce2df753f786188f382229278b4cdf23", + "sha256:6df9aa9599eb05ca179fb0b810282255202a66835c6efb1d112d21ecb830ddd3", + "sha256:7a3afa222f6fd3d9dfecd52729bc2e12c93e22a7491405a0ecbf9e1d32d45b39", + "sha256:7eb7bd2b56ea3bedb009616d9e2f64aab8fc7000d481faec3cd26c98a964bcdd", + "sha256:92116039b5500633cc8d44ecc187abe2dfa9b90f7a82bbf81d079fcdd506bae9", + "sha256:a2e658a9630f27534e63922ebf655a6ab60c370f4d2fc5c02a5b19baf4410ace", + "sha256:bfb20cb57486c8e4793d41996652e5a6a885b4d9175dd369045dad59eaacea42", + "sha256:caad2846e21188797a1f17fc09c31b84c7c3c23baf2516fed5b40b378515bbf0", + "sha256:d915a18f0597ef685e88bb35e5d7ab968964b7befefe1aaea1eb5b2640b586c7", + "sha256:dda73bf69ea479c8577a0448f8c707691152e6c4de7f0c4dec5a4bc11dee516e", + "sha256:e38beb7992b5afd9d5244e96ad5fa9135e94993b0c551ceebf3fe1a5d9beb234", + "sha256:edcc9f58ec0fd121a25bc950d4578df47428d72e1a0d66c07403b04eb93bcf98", + "sha256:efd3fdd3f67a7e576dd869c184c5dd71d9aaa36ded271939da352880c012e703", + "sha256:f696d6be15be87aef621917585f9bb94b1dc9e8aced570db1b8a6fc14e8f9b42", + "sha256:fd97ed11a4c7f6d042d320ce03d83b20c3fb40da892f994bc041bbc415d7a099" ], "markers": "python_version >= '3.8'", - "version": "==1.8.0" + "version": "==1.8.1" }, "decorator": { "hashes": [ @@ -676,11 +777,11 @@ }, "execnet": { "hashes": [ - "sha256:88256416ae766bc9e8895c76a87928c0012183da3cc4fc18016e6f050e025f41", - "sha256:cc59bc4423742fd71ad227122eb0dd44db51efb3dc4095b45ac9a08c770096af" + "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc", + "sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3" ], - "markers": "python_version >= '3.7'", - "version": "==2.0.2" + "markers": "python_version >= '3.8'", + "version": "==2.1.1" }, "executing": { "hashes": [ @@ -692,18 +793,18 @@ }, "fastjsonschema": { "hashes": [ - "sha256:b9fd1a2dd6971dbc7fee280a95bd199ae0dd9ce22beb91cc75e9c1c528a5170e", - "sha256:e25df6647e1bc4a26070b700897b07b542ec898dd4f1f6ea013e7f6a88417225" + "sha256:3672b47bc94178c9f23dbb654bf47440155d4db9df5f7bc47643315f9c405cd0", + "sha256:e3126a94bdc4623d3de4485f8d468a12f02a67921315ddc87836d6e456dc789d" ], - "version": "==2.19.0" + "version": "==2.19.1" }, "filelock": { "hashes": [ - "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e", - "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c" + "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f", + "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a" ], "markers": "python_version >= '3.8'", - "version": "==3.13.1" + "version": "==3.14.0" }, "flake8": { "hashes": [ @@ -727,11 +828,19 @@ }, "fs-synapse": { "hashes": [ - "sha256:1c8fb5b1da3220d21d13a6e48642d8b75a913a9b4779b99d6de9fc6074167898", - "sha256:8d95badbd14a052eac06875bcefec4570d336bbe318f0aa7878c469a70dfd35f" + "sha256:3fe1397564b0a84e4f6ae9e07bf3a0d002623d486e591a965a89be4b3e392bf4", + "sha256:c4ec5c3d04d7fcc3a4115cdf496e1055a680893a2dfb1c649271fc240964efe9" ], - "markers": "python_version >= '3.8'", - "version": "==1.0.0" + "markers": "python_version < '3.12' and python_version >= '3.9'", + "version": "==2.0.1" + }, + "googleapis-common-protos": { + "hashes": [ + "sha256:17ad01b11d5f1d0171c06d3ba5c04c54474e883b66b949722b4938ee2694ef4e", + "sha256:ae45f75702f7c08b541f750854a678bd8f534a1a6bace6afe975f1d0a82d6632" + ], + "markers": "python_version >= '3.7'", + "version": "==1.63.0" }, "hypothesis": { "hashes": [ @@ -742,19 +851,19 @@ }, "identify": { "hashes": [ - "sha256:161558f9fe4559e1557e1bff323e8631f6a0e4837f7497767c1782832f16b62d", - "sha256:d40ce5fcd762817627670da8a7d8d8e65f24342d14539c59488dc603bf662e34" + "sha256:37d93f380f4de590500d9dba7db359d0d3da95ffe7f9de1753faa159e71e7dfa", + "sha256:e5e00f54165f9047fbebeb4a560f9acfb8af4c88232be60a488e9b68d122745d" ], "markers": "python_version >= '3.8'", - "version": "==2.5.33" + "version": "==2.5.36" }, "idna": { "hashes": [ - "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca", - "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f" + "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc", + "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0" ], "markers": "python_version >= '3.5'", - "version": "==3.6" + "version": "==3.7" }, "imagesize": { "hashes": [ @@ -766,11 +875,11 @@ }, "importlib-metadata": { "hashes": [ - "sha256:8a8a81bcf996e74fee46f0d16bd3eaa382a7eb20fd82445c3ad11f4090334116", - "sha256:dd0173e8f150d6815e098fd354f6414b0f079af4644ddfe90c71e2fc6174346d" + "sha256:1231cf92d825c9e03cfc4da076a16de6422c863558229ea0b22b675657463443", + "sha256:f0afba6205ad8f8947c7d338b5342d5db2afbfd82f9cbef7879a9539cc12eb9b" ], - "markers": "python_version >= '3.7'", - "version": "==4.13.0" + "markers": "python_version >= '3.8'", + "version": "==6.11.0" }, "iniconfig": { "hashes": [ @@ -782,33 +891,33 @@ }, "interrogate": { "hashes": [ - "sha256:a4ccc5cbd727c74acc98dee6f5e79ef264c0bcfa66b68d4e123069b2af89091a", - "sha256:b6f325f0aa84ac3ac6779d8708264d366102226c5af7d69058cecffcff7a6d6c" + "sha256:a320d6ec644dfd887cc58247a345054fc4d9f981100c45184470068f4b3719b0", + "sha256:b13ff4dd8403369670e2efe684066de9fcb868ad9d7f2b4095d8112142dc9d12" ], - "version": "==1.5.0" + "version": "==1.7.0" }, "ipykernel": { "hashes": [ - "sha256:7d5d594b6690654b4d299edba5e872dc17bb7396a8d0609c97cb7b8a1c605de6", - "sha256:dab88b47f112f9f7df62236511023c9bdeef67abc73af7c652e4ce4441601686" + "sha256:1181e653d95c6808039c509ef8e67c4126b3b3af7781496c7cbfb5ed938a27da", + "sha256:3d44070060f9475ac2092b760123fadf105d2e2493c24848b6691a7c4f42af5c" ], "markers": "python_version >= '3.8'", - "version": "==6.27.1" + "version": "==6.29.4" }, "ipython": { "hashes": [ - "sha256:ca6f079bb33457c66e233e4580ebfc4128855b4cf6370dddd73842a9563e8a27", - "sha256:e8267419d72d81955ec1177f8a29aaa90ac80ad647499201119e2f05e99aa397" + "sha256:010db3f8a728a578bb641fdd06c063b9fb8e96a9464c63aec6310fbcb5e80501", + "sha256:d7bf2f6c4314984e3e02393213bab8703cf163ede39672ce5918c51fe253a2a3" ], - "markers": "python_version >= '3.9'", - "version": "==8.18.1" + "markers": "python_version >= '3.10'", + "version": "==8.24.0" }, "isort": { "hashes": [ - "sha256:56a51732c25f94ca96f6721be206dd96a95f42950502eb26c1015d333bc6edb7", - "sha256:aaed790b463e8703fb1eddb831dfa8e8616bacde2c083bd557ef73c8189b7263" + "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109", + "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6" ], - "version": "==5.13.1" + "version": "==5.13.2" }, "jedi": { "hashes": [ @@ -820,125 +929,117 @@ }, "jinja2": { "hashes": [ - "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852", - "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61" + "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369", + "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d" ], "markers": "python_version >= '3.7'", - "version": "==3.1.2" + "version": "==3.1.4" }, "jsonschema": { "hashes": [ - "sha256:4f614fd46d8d61258610998997743ec5492a648b33cf478c1ddc23ed4598a5fa", - "sha256:ed6231f0429ecf966f5bc8dfef245998220549cbbcf140f913b7464c52c3b6b3" + "sha256:5b22d434a45935119af990552c862e5d6d564e8f6601206b305a61fdf661a2b7", + "sha256:ff4cfd6b1367a40e7bc6411caec72effadd3db0bbe5017de188f2d6108335802" ], "markers": "python_version >= '3.8'", - "version": "==4.20.0" + "version": "==4.22.0" }, "jsonschema-specifications": { "hashes": [ - "sha256:9472fc4fea474cd74bea4a2b190daeccb5a9e4db2ea80efcf7a1b582fc9a81b8", - "sha256:e74ba7c0a65e8cb49dc26837d6cfe576557084a8b423ed16a420984228104f93" + "sha256:48a76787b3e70f5ed53f1160d2b81f586e4ca6d1548c5de7085d1682674764cc", + "sha256:87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c" ], "markers": "python_version >= '3.8'", - "version": "==2023.11.2" + "version": "==2023.12.1" }, "jupyter-client": { "hashes": [ - "sha256:0642244bb83b4764ae60d07e010e15f0e2d275ec4e918a8f7b80fbbef3ca60c7", - "sha256:909c474dbe62582ae62b758bca86d6518c85234bdee2d908c778db6d72f39d99" + "sha256:3b7bd22f058434e3b9a7ea4b1500ed47de2713872288c0d511d19926f99b459f", + "sha256:e842515e2bab8e19186d89fdfea7abd15e39dd581f94e399f00e2af5a1652d3f" ], "markers": "python_version >= '3.8'", - "version": "==8.6.0" + "version": "==8.6.1" }, "jupyter-core": { "hashes": [ - "sha256:880b86053bf298a8724994f95e99b99130659022a4f7f45f563084b6223861d3", - "sha256:e11e02cd8ae0a9de5c6c44abf5727df9f2581055afe00b22183f621ba3585805" + "sha256:4f7315d2f6b4bcf2e3e7cb6e46772eba760ae459cd1f59d29eb57b0a01bd7409", + "sha256:aa5f8d32bbf6b431ac830496da7392035d6f61b4f54872f15c4bd2a9c3f536d9" ], "markers": "python_version >= '3.8'", - "version": "==5.5.0" - }, - "keyring": { - "hashes": [ - "sha256:17e49fb0d6883c2b4445359434dba95aad84aabb29bbff044ad0ed7100232eca", - "sha256:89cbd74d4683ed164c8082fb38619341097741323b3786905c6dac04d6915a55" - ], - "markers": "python_version >= '3.6'", - "version": "==23.4.1" + "version": "==5.7.2" }, "markupsafe": { "hashes": [ - "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e", - "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e", - "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431", - "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686", - "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c", - "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559", - "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc", - "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb", - "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939", - "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c", - "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0", - "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4", - "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9", - "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575", - "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba", - "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d", - "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd", - "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3", - "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00", - "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155", - "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac", - "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52", - "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f", - "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8", - "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b", - "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007", - "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24", - "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea", - "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198", - "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0", - "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee", - "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be", - "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2", - "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1", - "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707", - "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6", - "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c", - "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58", - "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823", - "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779", - "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636", - "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c", - "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad", - "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee", - "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc", - "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2", - "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48", - "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7", - "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e", - "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b", - "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa", - "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5", - "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e", - "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb", - "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9", - "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57", - "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc", - "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc", - "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2", - "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11" + "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf", + "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff", + "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f", + "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3", + "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532", + "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f", + "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617", + "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df", + "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4", + "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906", + "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f", + "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4", + "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8", + "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371", + "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2", + "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465", + "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52", + "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6", + "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169", + "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad", + "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2", + "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0", + "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029", + "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f", + "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a", + "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced", + "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5", + "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c", + "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf", + "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9", + "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb", + "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad", + "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3", + "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1", + "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46", + "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc", + "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a", + "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee", + "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900", + "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5", + "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea", + "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f", + "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5", + "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e", + "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a", + "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f", + "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50", + "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a", + "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b", + "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4", + "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff", + "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2", + "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46", + "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b", + "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf", + "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5", + "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5", + "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab", + "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd", + "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68" ], "markers": "python_version >= '3.7'", - "version": "==2.1.3" + "version": "==2.1.5" }, "matplotlib-inline": { "hashes": [ - "sha256:f1f41aab5328aa5aaea9b16d083b128102f8712542f819fe7e6a420ff581b311", - "sha256:f887e5f10ba98e8d2b150ddcf4702c1e5f8b3a20005eb0f74bfdbd360ee6f304" + "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90", + "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca" ], - "markers": "python_version >= '3.5'", - "version": "==0.1.6" + "markers": "python_version >= '3.8'", + "version": "==0.1.7" }, "mccabe": { "hashes": [ @@ -1001,26 +1102,26 @@ }, "nbformat": { "hashes": [ - "sha256:1c5172d786a41b82bcfd0c23f9e6b6f072e8fb49c39250219e4acfff1efe89e9", - "sha256:5f98b5ba1997dff175e77e0c17d5c10a96eaed2cbd1de3533d1fc35d5e111192" + "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a", + "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b" ], "markers": "python_version >= '3.8'", - "version": "==5.9.2" + "version": "==5.10.4" }, "nbmake": { "hashes": [ - "sha256:233603c9186c659cb42524de36b556197c352ede1f9daeaa1b1141dfad226218", - "sha256:874c5b9d99922f88bf0c92a3b869e75bff154edba2538efef0a1d7ad2263f5fb" + "sha256:0b76b829e8b128eb1895539bacf515a1ee85e5b7b492cdfe76e3a12f804e069e", + "sha256:6cfa2b926d335e9c6dce7e8543d01b2398b0a56c03131c5c0bce2b1722116212" ], - "version": "==1.4.6" + "version": "==1.5.3" }, "nest-asyncio": { "hashes": [ - "sha256:25aa2ca0d2a5b5531956b9e273b45cf664cae2b145101d73b86b199978d48fdb", - "sha256:accda7a339a70599cb08f9dd09a67e0c2ef8d8d6f4c07f96ab203f2ae254e48d" + "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", + "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c" ], "markers": "python_version >= '3.5'", - "version": "==1.5.8" + "version": "==1.6.0" }, "nodeenv": { "hashes": [ @@ -1030,21 +1131,69 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", "version": "==1.8.0" }, + "opentelemetry-api": { + "hashes": [ + "sha256:4bb86b28627b7e41098f0e93280fe4892a1abed1b79a19aec6f928f39b17dffb", + "sha256:d6185fd5043e000075d921822fd2d26b953eba8ca21b1e2fa360dd46a7686316" + ], + "markers": "python_version >= '3.7'", + "version": "==1.21.0" + }, + "opentelemetry-exporter-otlp-proto-common": { + "hashes": [ + "sha256:61db274d8a68d636fb2ec2a0f281922949361cdd8236e25ff5539edf942b3226", + "sha256:97b1022b38270ec65d11fbfa348e0cd49d12006485c2321ea3b1b7037d42b6ec" + ], + "markers": "python_version >= '3.7'", + "version": "==1.21.0" + }, + "opentelemetry-exporter-otlp-proto-http": { + "hashes": [ + "sha256:19d60afa4ae8597f7ef61ad75c8b6c6b7ef8cb73a33fb4aed4dbc86d5c8d3301", + "sha256:56837773de6fb2714c01fc4895caebe876f6397bbc4d16afddf89e1299a55ee2" + ], + "markers": "python_version >= '3.7'", + "version": "==1.21.0" + }, + "opentelemetry-proto": { + "hashes": [ + "sha256:32fc4248e83eebd80994e13963e683f25f3b443226336bb12b5b6d53638f50ba", + "sha256:7d5172c29ed1b525b5ecf4ebe758c7138a9224441b3cfe683d0a237c33b1941f" + ], + "markers": "python_version >= '3.7'", + "version": "==1.21.0" + }, + "opentelemetry-sdk": { + "hashes": [ + "sha256:3ec8cd3020328d6bc5c9991ccaf9ae820ccb6395a5648d9a95d3ec88275b8879", + "sha256:9fe633243a8c655fedace3a0b89ccdfc654c0290ea2d8e839bd5db3131186f73" + ], + "markers": "python_version >= '3.7'", + "version": "==1.21.0" + }, + "opentelemetry-semantic-conventions": { + "hashes": [ + "sha256:44ae67a0a3252a05072877857e5cc1242c98d4cf12870159f1a94bec800d38ec", + "sha256:5cd719cbfec448af658860796c5d0fcea2fdf0945a2bed2363f42cb1ee39f526" + ], + "markers": "python_version >= '3.7'", + "version": "==0.42b0" + }, "packaging": { "hashes": [ - "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", - "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" + "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5", + "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9" ], "markers": "python_version >= '3.7'", - "version": "==23.2" + "version": "==24.0" }, "parso": { "hashes": [ - "sha256:8c07be290bb59f03588915921e29e8a50002acaf2cdc5fa0e0114f91709fafa0", - "sha256:c001d4636cd3aecdaf33cbb40aebb59b094be2a74c556778ef5576c175e19e75" + "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18", + "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d" ], "markers": "python_version >= '3.6'", - "version": "==0.8.3" + "version": "==0.8.4" }, "pathspec": { "hashes": [ @@ -1059,24 +1208,24 @@ "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f" ], - "markers": "sys_platform != 'win32'", + "markers": "sys_platform != 'win32' and sys_platform != 'emscripten'", "version": "==4.9.0" }, "platformdirs": { "hashes": [ - "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380", - "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420" + "sha256:031cd18d4ec63ec53e82dceaac0417d218a6863f7745dfcc9efe7793b7039bdf", + "sha256:17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1" ], "markers": "python_version >= '3.8'", - "version": "==4.1.0" + "version": "==4.2.1" }, "pluggy": { "hashes": [ - "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12", - "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7" + "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", + "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669" ], "markers": "python_version >= '3.8'", - "version": "==1.3.0" + "version": "==1.5.0" }, "pre-commit": { "hashes": [ @@ -1093,26 +1242,43 @@ "markers": "python_full_version >= '3.7.0'", "version": "==3.0.43" }, + "protobuf": { + "hashes": [ + "sha256:19b270aeaa0099f16d3ca02628546b8baefe2955bbe23224aaf856134eccf1e4", + "sha256:209ba4cc916bab46f64e56b85b090607a676f66b473e6b762e6f1d9d591eb2e8", + "sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c", + "sha256:7c8daa26095f82482307bc717364e7c13f4f1c99659be82890dcfc215194554d", + "sha256:c053062984e61144385022e53678fbded7aea14ebb3e0305ae3592fb219ccfa4", + "sha256:d4198877797a83cbfe9bffa3803602bbe1625dc30d8a097365dbc762e5790faa", + "sha256:e3c97a1555fd6388f857770ff8b9703083de6bf1f9274a002a332d65fbb56c8c", + "sha256:e7cb0ae90dd83727f0c0718634ed56837bfeeee29a5f82a7514c03ee1364c019", + "sha256:f0700d54bcf45424477e46a9f0944155b46fb0639d69728739c0e47bab83f2b9", + "sha256:f1279ab38ecbfae7e456a108c5c0681e4956d5b1090027c1de0f934dfdb4b35c", + "sha256:f4f118245c4a087776e0a8408be33cf09f6c547442c00395fbfb116fac2f8ac2" + ], + "markers": "python_version >= '3.8'", + "version": "==4.25.3" + }, "psutil": { "hashes": [ - "sha256:10e8c17b4f898d64b121149afb136c53ea8b68c7531155147867b7b1ac9e7e28", - "sha256:18cd22c5db486f33998f37e2bb054cc62fd06646995285e02a51b1e08da97017", - "sha256:3ebf2158c16cc69db777e3c7decb3c0f43a7af94a60d72e87b2823aebac3d602", - "sha256:51dc3d54607c73148f63732c727856f5febec1c7c336f8f41fcbd6315cce76ac", - "sha256:6e5fb8dc711a514da83098bc5234264e551ad980cec5f85dabf4d38ed6f15e9a", - "sha256:70cb3beb98bc3fd5ac9ac617a327af7e7f826373ee64c80efd4eb2856e5051e9", - "sha256:748c9dd2583ed86347ed65d0035f45fa8c851e8d90354c122ab72319b5f366f4", - "sha256:91ecd2d9c00db9817a4b4192107cf6954addb5d9d67a969a4f436dbc9200f88c", - "sha256:92e0cc43c524834af53e9d3369245e6cc3b130e78e26100d1f63cdb0abeb3d3c", - "sha256:a6f01f03bf1843280f4ad16f4bde26b817847b4c1a0db59bf6419807bc5ce05c", - "sha256:c69596f9fc2f8acd574a12d5f8b7b1ba3765a641ea5d60fb4736bf3c08a8214a", - "sha256:ca2780f5e038379e520281e4c032dddd086906ddff9ef0d1b9dcf00710e5071c", - "sha256:daecbcbd29b289aac14ece28eca6a3e60aa361754cf6da3dfb20d4d32b6c7f57", - "sha256:e4b92ddcd7dd4cdd3f900180ea1e104932c7bce234fb88976e2a3b296441225a", - "sha256:fb8a697f11b0f5994550555fcfe3e69799e5b060c8ecf9e2f75c69302cc35c0d", - "sha256:ff18b8d1a784b810df0b0fff3bcb50ab941c3b8e2c8de5726f9c71c601c611aa" - ], - "version": "==5.9.6" + "sha256:02615ed8c5ea222323408ceba16c60e99c3f91639b07da6373fb7e6539abc56d", + "sha256:05806de88103b25903dff19bb6692bd2e714ccf9e668d050d144012055cbca73", + "sha256:26bd09967ae00920df88e0352a91cff1a78f8d69b3ecabbfe733610c0af486c8", + "sha256:27cc40c3493bb10de1be4b3f07cae4c010ce715290a5be22b98493509c6299e2", + "sha256:36f435891adb138ed3c9e58c6af3e2e6ca9ac2f365efe1f9cfef2794e6c93b4e", + "sha256:50187900d73c1381ba1454cf40308c2bf6f34268518b3f36a9b663ca87e65e36", + "sha256:611052c4bc70432ec770d5d54f64206aa7203a101ec273a0cd82418c86503bb7", + "sha256:6be126e3225486dff286a8fb9a06246a5253f4c7c53b475ea5f5ac934e64194c", + "sha256:7d79560ad97af658a0f6adfef8b834b53f64746d45b403f225b85c5c2c140eee", + "sha256:8cb6403ce6d8e047495a701dc7c5bd788add903f8986d523e3e20b98b733e421", + "sha256:8db4c1b57507eef143a15a6884ca10f7c73876cdf5d51e713151c1236a0e68cf", + "sha256:aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81", + "sha256:bc56c2a1b0d15aa3eaa5a60c9f3f8e3e565303b465dbf57a1b730e7a2b9844e0", + "sha256:bd1184ceb3f87651a67b2708d4c3338e9b10c5df903f2e3776b62303b26cb631", + "sha256:d06016f7f8625a1825ba3732081d77c94589dca78b7a3fc072194851e88461a4", + "sha256:d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8" + ], + "version": "==5.9.8" }, "ptyprocess": { "hashes": [ @@ -1154,18 +1320,18 @@ }, "pygments": { "hashes": [ - "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c", - "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367" + "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199", + "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a" ], - "markers": "python_version >= '3.7'", - "version": "==2.17.2" + "markers": "python_version >= '3.8'", + "version": "==2.18.0" }, "pytest": { "hashes": [ - "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac", - "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5" + "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280", + "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8" ], - "version": "==7.4.3" + "version": "==7.4.4" }, "pytest-cov": { "hashes": [ @@ -1176,28 +1342,28 @@ }, "pytest-mock": { "hashes": [ - "sha256:0972719a7263072da3a21c7f4773069bcc7486027d7e8e1f81d98a47e701bc4f", - "sha256:31a40f038c22cad32287bb43932054451ff5583ff094bca6f675df2f8bc1a6e9" + "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f", + "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0" ], - "version": "==3.12.0" + "version": "==3.14.0" }, "pytest-xdist": { "extras": [ "psutil" ], "hashes": [ - "sha256:cbb36f3d67e0c478baa57fa4edc8843887e0f6cfc42d677530a36d7472b32d8a", - "sha256:d075629c7e00b611df89f490a5063944bee7a4362a5ff11c7cc7824a03dfce24" + "sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7", + "sha256:ead156a4db231eec769737f57668ef58a2084a34b2e55c4a8fa20d861107300d" ], - "version": "==3.5.0" + "version": "==3.6.1" }, "python-dateutil": { "hashes": [ - "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", - "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" + "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", + "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", - "version": "==2.8.2" + "version": "==2.9.0.post0" }, "pyyaml": { "hashes": [ @@ -1230,6 +1396,7 @@ "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba", "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8", + "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef", "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5", "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd", "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3", @@ -1257,110 +1424,105 @@ }, "pyzmq": { "hashes": [ - "sha256:004ff469d21e86f0ef0369717351073e0e577428e514c47c8480770d5e24a565", - "sha256:00a06faa7165634f0cac1abb27e54d7a0b3b44eb9994530b8ec73cf52e15353b", - "sha256:00c48ae2fd81e2a50c3485de1b9d5c7c57cd85dc8ec55683eac16846e57ac979", - "sha256:01171fc48542348cd1a360a4b6c3e7d8f46cdcf53a8d40f84db6707a6768acc1", - "sha256:019744b99da30330798bb37df33549d59d380c78e516e3bab9c9b84f87a9592f", - "sha256:02bbc1a87b76e04fd780b45e7f695471ae6de747769e540da909173d50ff8e2d", - "sha256:02c9087b109070c5ab0b383079fa1b5f797f8d43e9a66c07a4b8b8bdecfd88ee", - "sha256:07cd61a20a535524906595e09344505a9bd46f1da7a07e504b315d41cd42eb07", - "sha256:0806175f2ae5ad4b835ecd87f5f85583316b69f17e97786f7443baaf54b9bb98", - "sha256:09dfe949e83087da88c4a76767df04b22304a682d6154de2c572625c62ad6886", - "sha256:0dabfb10ef897f3b7e101cacba1437bd3a5032ee667b7ead32bbcdd1a8422fe7", - "sha256:0ddd6d71d4ef17ba5a87becf7ddf01b371eaba553c603477679ae817a8d84d75", - "sha256:0f513130c4c361201da9bc69df25a086487250e16b5571ead521b31ff6b02220", - "sha256:0f97bc2f1f13cb16905a5f3e1fbdf100e712d841482b2237484360f8bc4cb3d7", - "sha256:11e70516688190e9c2db14fcf93c04192b02d457b582a1f6190b154691b4c93a", - "sha256:146b9b1f29ead41255387fb07be56dc29639262c0f7344f570eecdcd8d683314", - "sha256:16b726c1f6c2e7625706549f9dbe9b06004dfbec30dbed4bf50cbdfc73e5b32a", - "sha256:1b3cbba2f47062b85fe0ef9de5b987612140a9ba3a9c6d2543c6dec9f7c2ab27", - "sha256:1b9b1f2ad6498445a941d9a4fee096d387fee436e45cc660e72e768d3d8ee611", - "sha256:1ec23bd7b3a893ae676d0e54ad47d18064e6c5ae1fadc2f195143fb27373f7f6", - "sha256:246747b88917e4867e2367b005fc8eefbb4a54b7db363d6c92f89d69abfff4b6", - "sha256:25c2dbb97d38b5ac9fd15586e048ec5eb1e38f3d47fe7d92167b0c77bb3584e9", - "sha256:2c6441e0398c2baacfe5ba30c937d274cfc2dc5b55e82e3749e333aabffde561", - "sha256:2c9a79f1d2495b167119d02be7448bfba57fad2a4207c4f68abc0bab4b92925b", - "sha256:2e2713ef44be5d52dd8b8e2023d706bf66cb22072e97fc71b168e01d25192755", - "sha256:313c3794d650d1fccaaab2df942af9f2c01d6217c846177cfcbc693c7410839e", - "sha256:3516e0b6224cf6e43e341d56da15fd33bdc37fa0c06af4f029f7d7dfceceabbc", - "sha256:359f7f74b5d3c65dae137f33eb2bcfa7ad9ebefd1cab85c935f063f1dbb245cc", - "sha256:39b1067f13aba39d794a24761e385e2eddc26295826530a8c7b6c6c341584289", - "sha256:3c00c9b7d1ca8165c610437ca0c92e7b5607b2f9076f4eb4b095c85d6e680a1d", - "sha256:3c53687dde4d9d473c587ae80cc328e5b102b517447456184b485587ebd18b62", - "sha256:3e124e6b1dd3dfbeb695435dff0e383256655bb18082e094a8dd1f6293114642", - "sha256:4345c9a27f4310afbb9c01750e9461ff33d6fb74cd2456b107525bbeebcb5be3", - "sha256:45999e7f7ed5c390f2e87ece7f6c56bf979fb213550229e711e45ecc7d42ccb8", - "sha256:49151b0efece79f6a79d41a461d78535356136ee70084a1c22532fc6383f4ad0", - "sha256:4cb8fc1f8d69b411b8ec0b5f1ffbcaf14c1db95b6bccea21d83610987435f1a4", - "sha256:4e5837af3e5aaa99a091302df5ee001149baff06ad22b722d34e30df5f0d9097", - "sha256:4e6f689880d5ad87918430957297c975203a082d9a036cc426648fcbedae769b", - "sha256:5074adeacede5f810b7ef39607ee59d94e948b4fd954495bdb072f8c54558181", - "sha256:518efd91c3d8ac9f9b4f7dd0e2b7b8bf1a4fe82a308009016b07eaa48681af82", - "sha256:55875492f820d0eb3417b51d96fea549cde77893ae3790fd25491c5754ea2f68", - "sha256:5a68d491fc20762b630e5db2191dd07ff89834086740f70e978bb2ef2668be08", - "sha256:5dde6751e857910c1339890f3524de74007958557593b9e7e8c5f01cd919f8a7", - "sha256:5e319ed7d6b8f5fad9b76daa0a68497bc6f129858ad956331a5835785761e003", - "sha256:5edac3f57c7ddaacdb4d40f6ef2f9e299471fc38d112f4bc6d60ab9365445fb0", - "sha256:6cc0020b74b2e410287e5942e1e10886ff81ac77789eb20bec13f7ae681f0fdd", - "sha256:6dd0d50bbf9dca1d0bdea219ae6b40f713a3fb477c06ca3714f208fd69e16fd8", - "sha256:7598d2ba821caa37a0f9d54c25164a4fa351ce019d64d0b44b45540950458840", - "sha256:759cfd391a0996345ba94b6a5110fca9c557ad4166d86a6e81ea526c376a01e8", - "sha256:7ae8f354b895cbd85212da245f1a5ad8159e7840e37d78b476bb4f4c3f32a9fe", - "sha256:7b6d09a8962a91151f0976008eb7b29b433a560fde056ec7a3db9ec8f1075438", - "sha256:7c61e346ac34b74028ede1c6b4bcecf649d69b707b3ff9dc0fab453821b04d1e", - "sha256:7f51a7b4ead28d3fca8dda53216314a553b0f7a91ee8fc46a72b402a78c3e43d", - "sha256:82544e0e2d0c1811482d37eef297020a040c32e0687c1f6fc23a75b75db8062c", - "sha256:8807c87fa893527ae8a524c15fc505d9950d5e856f03dae5921b5e9aa3b8783b", - "sha256:889370d5174a741a62566c003ee8ddba4b04c3f09a97b8000092b7ca83ec9c49", - "sha256:8b14c75979ce932c53b79976a395cb2a8cd3aaf14aef75e8c2cb55a330b9b49d", - "sha256:8c5f80e578427d4695adac6fdf4370c14a2feafdc8cb35549c219b90652536ae", - "sha256:8e9f3fabc445d0ce320ea2c59a75fe3ea591fdbdeebec5db6de530dd4b09412e", - "sha256:93f1aa311e8bb912e34f004cf186407a4e90eec4f0ecc0efd26056bf7eda0226", - "sha256:94504ff66f278ab4b7e03e4cba7e7e400cb73bfa9d3d71f58d8972a8dc67e7a6", - "sha256:967668420f36878a3c9ecb5ab33c9d0ff8d054f9c0233d995a6d25b0e95e1b6b", - "sha256:9880078f683466b7f567b8624bfc16cad65077be046b6e8abb53bed4eeb82dd3", - "sha256:99a6b36f95c98839ad98f8c553d8507644c880cf1e0a57fe5e3a3f3969040882", - "sha256:9a18fff090441a40ffda8a7f4f18f03dc56ae73f148f1832e109f9bffa85df15", - "sha256:9add2e5b33d2cd765ad96d5eb734a5e795a0755f7fc49aa04f76d7ddda73fd70", - "sha256:a793ac733e3d895d96f865f1806f160696422554e46d30105807fdc9841b9f7d", - "sha256:a86c2dd76ef71a773e70551a07318b8e52379f58dafa7ae1e0a4be78efd1ff16", - "sha256:a8c1d566344aee826b74e472e16edae0a02e2a044f14f7c24e123002dcff1c05", - "sha256:ac170e9e048b40c605358667aca3d94e98f604a18c44bdb4c102e67070f3ac9b", - "sha256:b264bf2cc96b5bc43ce0e852be995e400376bd87ceb363822e2cb1964fcdc737", - "sha256:b8c8a419dfb02e91b453615c69568442e897aaf77561ee0064d789705ff37a92", - "sha256:bc69c96735ab501419c432110016329bf0dea8898ce16fab97c6d9106dc0b348", - "sha256:bef02cfcbded83473bdd86dd8d3729cd82b2e569b75844fb4ea08fee3c26ae41", - "sha256:c0b5ca88a8928147b7b1e2dfa09f3b6c256bc1135a1338536cbc9ea13d3b7add", - "sha256:cc69949484171cc961e6ecd4a8911b9ce7a0d1f738fcae717177c231bf77437b", - "sha256:ced111c2e81506abd1dc142e6cd7b68dd53747b3b7ae5edbea4578c5eeff96b7", - "sha256:d1299d7e964c13607efd148ca1f07dcbf27c3ab9e125d1d0ae1d580a1682399d", - "sha256:d1b604734bec94f05f81b360a272fc824334267426ae9905ff32dc2be433ab96", - "sha256:d9a5f194cf730f2b24d6af1f833c14c10f41023da46a7f736f48b6d35061e76e", - "sha256:db36c27baed588a5a8346b971477b718fdc66cf5b80cbfbd914b4d6d355e44e2", - "sha256:df0c7a16ebb94452d2909b9a7b3337940e9a87a824c4fc1c7c36bb4404cb0cde", - "sha256:e10a4b5a4b1192d74853cc71a5e9fd022594573926c2a3a4802020360aa719d8", - "sha256:e624c789359f1a16f83f35e2c705d07663ff2b4d4479bad35621178d8f0f6ea4", - "sha256:e690145a8c0c273c28d3b89d6fb32c45e0d9605b2293c10e650265bf5c11cfec", - "sha256:ea1608dd169da230a0ad602d5b1ebd39807ac96cae1845c3ceed39af08a5c6df", - "sha256:ea253b368eb41116011add00f8d5726762320b1bda892f744c91997b65754d73", - "sha256:eb7e49a17fb8c77d3119d41a4523e432eb0c6932187c37deb6fbb00cc3028088", - "sha256:ef12e259e7bc317c7597d4f6ef59b97b913e162d83b421dd0db3d6410f17a244", - "sha256:f8429b17cbb746c3e043cb986328da023657e79d5ed258b711c06a70c2ea7537", - "sha256:fa99973d2ed20417744fca0073390ad65ce225b546febb0580358e36aa90dba6", - "sha256:faf79a302f834d9e8304fafdc11d0d042266667ac45209afa57e5efc998e3872", - "sha256:fc31baa0c32a2ca660784d5af3b9487e13b61b3032cb01a115fce6588e1bed30" + "sha256:01fbfbeb8249a68d257f601deb50c70c929dc2dfe683b754659569e502fbd3aa", + "sha256:0270b49b6847f0d106d64b5086e9ad5dc8a902413b5dbbb15d12b60f9c1747a4", + "sha256:03c0ae165e700364b266876d712acb1ac02693acd920afa67da2ebb91a0b3c09", + "sha256:068ca17214038ae986d68f4a7021f97e187ed278ab6dccb79f837d765a54d753", + "sha256:082a2988364b60bb5de809373098361cf1dbb239623e39e46cb18bc035ed9c0c", + "sha256:0aaf982e68a7ac284377d051c742610220fd06d330dcd4c4dbb4cdd77c22a537", + "sha256:0c0991f5a96a8e620f7691e61178cd8f457b49e17b7d9cfa2067e2a0a89fc1d5", + "sha256:115f8359402fa527cf47708d6f8a0f8234f0e9ca0cab7c18c9c189c194dbf620", + "sha256:15c59e780be8f30a60816a9adab900c12a58d79c1ac742b4a8df044ab2a6d920", + "sha256:1b7d0e124948daa4d9686d421ef5087c0516bc6179fdcf8828b8444f8e461a77", + "sha256:1c8eb19abe87029c18f226d42b8a2c9efdd139d08f8bf6e085dd9075446db450", + "sha256:204e0f176fd1d067671157d049466869b3ae1fc51e354708b0dc41cf94e23a3a", + "sha256:2136f64fbb86451dbbf70223635a468272dd20075f988a102bf8a3f194a411dc", + "sha256:2b291d1230845871c00c8462c50565a9cd6026fe1228e77ca934470bb7d70ea0", + "sha256:2c18645ef6294d99b256806e34653e86236eb266278c8ec8112622b61db255de", + "sha256:2cc4e280098c1b192c42a849de8de2c8e0f3a84086a76ec5b07bfee29bda7d18", + "sha256:2ed8357f4c6e0daa4f3baf31832df8a33334e0fe5b020a61bc8b345a3db7a606", + "sha256:3191d312c73e3cfd0f0afdf51df8405aafeb0bad71e7ed8f68b24b63c4f36500", + "sha256:3401613148d93ef0fd9aabdbddb212de3db7a4475367f49f590c837355343972", + "sha256:34106f68e20e6ff253c9f596ea50397dbd8699828d55e8fa18bd4323d8d966e6", + "sha256:3516119f4f9b8671083a70b6afaa0a070f5683e431ab3dc26e9215620d7ca1ad", + "sha256:38ece17ec5f20d7d9b442e5174ae9f020365d01ba7c112205a4d59cf19dc38ee", + "sha256:3b4032a96410bdc760061b14ed6a33613ffb7f702181ba999df5d16fb96ba16a", + "sha256:3bf8b000a4e2967e6dfdd8656cd0757d18c7e5ce3d16339e550bd462f4857e59", + "sha256:3e3070e680f79887d60feeda051a58d0ac36622e1759f305a41059eff62c6da7", + "sha256:4496b1282c70c442809fc1b151977c3d967bfb33e4e17cedbf226d97de18f709", + "sha256:44dd6fc3034f1eaa72ece33588867df9e006a7303725a12d64c3dff92330f625", + "sha256:4adfbb5451196842a88fda3612e2c0414134874bffb1c2ce83ab4242ec9e027d", + "sha256:4b7c0c0b3244bb2275abe255d4a30c050d541c6cb18b870975553f1fb6f37527", + "sha256:4c82a6d952a1d555bf4be42b6532927d2a5686dd3c3e280e5f63225ab47ac1f5", + "sha256:5344b896e79800af86ad643408ca9aa303a017f6ebff8cee5a3163c1e9aec987", + "sha256:5bde86a2ed3ce587fa2b207424ce15b9a83a9fa14422dcc1c5356a13aed3df9d", + "sha256:5bf6c237f8c681dfb91b17f8435b2735951f0d1fad10cc5dfd96db110243370b", + "sha256:5dbb9c997932473a27afa93954bb77a9f9b786b4ccf718d903f35da3232317de", + "sha256:69ea9d6d9baa25a4dc9cef5e2b77b8537827b122214f210dd925132e34ae9b12", + "sha256:6b3146f9ae6af82c47a5282ac8803523d381b3b21caeae0327ed2f7ecb718798", + "sha256:6bcb34f869d431799c3ee7d516554797f7760cb2198ecaa89c3f176f72d062be", + "sha256:6ca08b840fe95d1c2bd9ab92dac5685f949fc6f9ae820ec16193e5ddf603c3b2", + "sha256:6ca7a9a06b52d0e38ccf6bca1aeff7be178917893f3883f37b75589d42c4ac20", + "sha256:703c60b9910488d3d0954ca585c34f541e506a091a41930e663a098d3b794c67", + "sha256:715bdf952b9533ba13dfcf1f431a8f49e63cecc31d91d007bc1deb914f47d0e4", + "sha256:72b67f966b57dbd18dcc7efbc1c7fc9f5f983e572db1877081f075004614fcdd", + "sha256:74423631b6be371edfbf7eabb02ab995c2563fee60a80a30829176842e71722a", + "sha256:77a85dca4c2430ac04dc2a2185c2deb3858a34fe7f403d0a946fa56970cf60a1", + "sha256:7821d44fe07335bea256b9f1f41474a642ca55fa671dfd9f00af8d68a920c2d4", + "sha256:788f15721c64109cf720791714dc14afd0f449d63f3a5487724f024345067381", + "sha256:7ca684ee649b55fd8f378127ac8462fb6c85f251c2fb027eb3c887e8ee347bcd", + "sha256:7daa3e1369355766dea11f1d8ef829905c3b9da886ea3152788dc25ee6079e02", + "sha256:7e6bc96ebe49604df3ec2c6389cc3876cabe475e6bfc84ced1bf4e630662cb35", + "sha256:80b12f25d805a919d53efc0a5ad7c0c0326f13b4eae981a5d7b7cc343318ebb7", + "sha256:871587bdadd1075b112e697173e946a07d722459d20716ceb3d1bd6c64bd08ce", + "sha256:88b88282e55fa39dd556d7fc04160bcf39dea015f78e0cecec8ff4f06c1fc2b5", + "sha256:8d7a498671ca87e32b54cb47c82a92b40130a26c5197d392720a1bce1b3c77cf", + "sha256:926838a535c2c1ea21c903f909a9a54e675c2126728c21381a94ddf37c3cbddf", + "sha256:971e8990c5cc4ddcff26e149398fc7b0f6a042306e82500f5e8db3b10ce69f84", + "sha256:9b273ecfbc590a1b98f014ae41e5cf723932f3b53ba9367cfb676f838038b32c", + "sha256:a42db008d58530efa3b881eeee4991146de0b790e095f7ae43ba5cc612decbc5", + "sha256:a72a84570f84c374b4c287183debc776dc319d3e8ce6b6a0041ce2e400de3f32", + "sha256:ac97a21de3712afe6a6c071abfad40a6224fd14fa6ff0ff8d0c6e6cd4e2f807a", + "sha256:acb704195a71ac5ea5ecf2811c9ee19ecdc62b91878528302dd0be1b9451cc90", + "sha256:b32bff85fb02a75ea0b68f21e2412255b5731f3f389ed9aecc13a6752f58ac97", + "sha256:b3cd31f859b662ac5d7f4226ec7d8bd60384fa037fc02aee6ff0b53ba29a3ba8", + "sha256:b63731993cdddcc8e087c64e9cf003f909262b359110070183d7f3025d1c56b5", + "sha256:b6907da3017ef55139cf0e417c5123a84c7332520e73a6902ff1f79046cd3b94", + "sha256:ba6e5e6588e49139a0979d03a7deb9c734bde647b9a8808f26acf9c547cab1bf", + "sha256:c1c8f2a2ca45292084c75bb6d3a25545cff0ed931ed228d3a1810ae3758f975f", + "sha256:ce828058d482ef860746bf532822842e0ff484e27f540ef5c813d516dd8896d2", + "sha256:d0a2d1bd63a4ad79483049b26514e70fa618ce6115220da9efdff63688808b17", + "sha256:d0cdde3c78d8ab5b46595054e5def32a755fc028685add5ddc7403e9f6de9879", + "sha256:d57dfbf9737763b3a60d26e6800e02e04284926329aee8fb01049635e957fe81", + "sha256:d8416c23161abd94cc7da80c734ad7c9f5dbebdadfdaa77dad78244457448223", + "sha256:dba7d9f2e047dfa2bca3b01f4f84aa5246725203d6284e3790f2ca15fba6b40a", + "sha256:dbf012d8fcb9f2cf0643b65df3b355fdd74fc0035d70bb5c845e9e30a3a4654b", + "sha256:e1258c639e00bf5e8a522fec6c3eaa3e30cf1c23a2f21a586be7e04d50c9acab", + "sha256:e222562dc0f38571c8b1ffdae9d7adb866363134299264a1958d077800b193b7", + "sha256:e4946d6bdb7ba972dfda282f9127e5756d4f299028b1566d1245fa0d438847e6", + "sha256:e746524418b70f38550f2190eeee834db8850088c834d4c8406fbb9bc1ae10b2", + "sha256:e76654e9dbfb835b3518f9938e565c7806976c07b37c33526b574cc1a1050480", + "sha256:e8918973fbd34e7814f59143c5f600ecd38b8038161239fd1a3d33d5817a38b8", + "sha256:e891ce81edd463b3b4c3b885c5603c00141151dd9c6936d98a680c8c72fe5c67", + "sha256:ebbbd0e728af5db9b04e56389e2299a57ea8b9dd15c9759153ee2455b32be6ad", + "sha256:eeb438a26d87c123bb318e5f2b3d86a36060b01f22fbdffd8cf247d52f7c9a2b", + "sha256:eed56b6a39216d31ff8cd2f1d048b5bf1700e4b32a01b14379c3b6dde9ce3aa3", + "sha256:f17cde1db0754c35a91ac00b22b25c11da6eec5746431d6e5092f0cd31a3fea9", + "sha256:f1a9b7d00fdf60b4039f4455afd031fe85ee8305b019334b72dcf73c567edc47", + "sha256:f4b6cecbbf3b7380f3b61de3a7b93cb721125dc125c854c14ddc91225ba52f83", + "sha256:f6b1d1c631e5940cac5a0b22c5379c86e8df6a4ec277c7a856b714021ab6cfad", + "sha256:f6c21c00478a7bea93caaaef9e7629145d4153b15a8653e8bb4609d4bc70dbfc" ], - "markers": "python_version >= '3.6'", - "version": "==25.1.2" + "markers": "python_version >= '3.7'", + "version": "==26.0.3" }, "referencing": { "hashes": [ - "sha256:689e64fe121843dcfd57b71933318ef1f91188ffb45367332700a86ac8fd6161", - "sha256:bdcd3efb936f82ff86f993093f6da7435c7de69a3b3a5a06678a6050184bee99" + "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c", + "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de" ], "markers": "python_version >= '3.8'", - "version": "==0.32.0" + "version": "==0.35.1" }, "requests": { "hashes": [ @@ -1372,116 +1534,116 @@ }, "rpds-py": { "hashes": [ - "sha256:06d218e4464d31301e943b65b2c6919318ea6f69703a351961e1baaf60347276", - "sha256:12ecf89bd54734c3c2c79898ae2021dca42750c7bcfb67f8fb3315453738ac8f", - "sha256:15253fff410873ebf3cfba1cc686a37711efcd9b8cb30ea21bb14a973e393f60", - "sha256:188435794405c7f0573311747c85a96b63c954a5f2111b1df8018979eca0f2f0", - "sha256:1ceebd0ae4f3e9b2b6b553b51971921853ae4eebf3f54086be0565d59291e53d", - "sha256:244e173bb6d8f3b2f0c4d7370a1aa341f35da3e57ffd1798e5b2917b91731fd3", - "sha256:25b28b3d33ec0a78e944aaaed7e5e2a94ac811bcd68b557ca48a0c30f87497d2", - "sha256:25ea41635d22b2eb6326f58e608550e55d01df51b8a580ea7e75396bafbb28e9", - "sha256:29d311e44dd16d2434d5506d57ef4d7036544fc3c25c14b6992ef41f541b10fb", - "sha256:2a1472956c5bcc49fb0252b965239bffe801acc9394f8b7c1014ae9258e4572b", - "sha256:2a7bef6977043673750a88da064fd513f89505111014b4e00fbdd13329cd4e9a", - "sha256:2ac26f50736324beb0282c819668328d53fc38543fa61eeea2c32ea8ea6eab8d", - "sha256:2e72f750048b32d39e87fc85c225c50b2a6715034848dbb196bf3348aa761fa1", - "sha256:31e220a040b89a01505128c2f8a59ee74732f666439a03e65ccbf3824cdddae7", - "sha256:35f53c76a712e323c779ca39b9a81b13f219a8e3bc15f106ed1e1462d56fcfe9", - "sha256:38d4f822ee2f338febcc85aaa2547eb5ba31ba6ff68d10b8ec988929d23bb6b4", - "sha256:38f9bf2ad754b4a45b8210a6c732fe876b8a14e14d5992a8c4b7c1ef78740f53", - "sha256:3a44c8440183b43167fd1a0819e8356692bf5db1ad14ce140dbd40a1485f2dea", - "sha256:3ab96754d23372009638a402a1ed12a27711598dd49d8316a22597141962fe66", - "sha256:3c55d7f2d817183d43220738270efd3ce4e7a7b7cbdaefa6d551ed3d6ed89190", - "sha256:46e1ed994a0920f350a4547a38471217eb86f57377e9314fbaaa329b71b7dfe3", - "sha256:4a5375c5fff13f209527cd886dc75394f040c7d1ecad0a2cb0627f13ebe78a12", - "sha256:4c2d26aa03d877c9730bf005621c92da263523a1e99247590abbbe252ccb7824", - "sha256:4c4e314d36d4f31236a545696a480aa04ea170a0b021e9a59ab1ed94d4c3ef27", - "sha256:4d0c10d803549427f427085ed7aebc39832f6e818a011dcd8785e9c6a1ba9b3e", - "sha256:4dcc5ee1d0275cb78d443fdebd0241e58772a354a6d518b1d7af1580bbd2c4e8", - "sha256:51967a67ea0d7b9b5cd86036878e2d82c0b6183616961c26d825b8c994d4f2c8", - "sha256:530190eb0cd778363bbb7596612ded0bb9fef662daa98e9d92a0419ab27ae914", - "sha256:5379e49d7e80dca9811b36894493d1c1ecb4c57de05c36f5d0dd09982af20211", - "sha256:5493569f861fb7b05af6d048d00d773c6162415ae521b7010197c98810a14cab", - "sha256:5a4c1058cdae6237d97af272b326e5f78ee7ee3bbffa6b24b09db4d828810468", - "sha256:5d75d6d220d55cdced2f32cc22f599475dbe881229aeddba6c79c2e9df35a2b3", - "sha256:5d97e9ae94fb96df1ee3cb09ca376c34e8a122f36927230f4c8a97f469994bff", - "sha256:5feae2f9aa7270e2c071f488fab256d768e88e01b958f123a690f1cc3061a09c", - "sha256:603d5868f7419081d616dab7ac3cfa285296735e7350f7b1e4f548f6f953ee7d", - "sha256:61d42d2b08430854485135504f672c14d4fc644dd243a9c17e7c4e0faf5ed07e", - "sha256:61dbc1e01dc0c5875da2f7ae36d6e918dc1b8d2ce04e871793976594aad8a57a", - "sha256:65cfed9c807c27dee76407e8bb29e6f4e391e436774bcc769a037ff25ad8646e", - "sha256:67a429520e97621a763cf9b3ba27574779c4e96e49a27ff8a1aa99ee70beb28a", - "sha256:6aadae3042f8e6db3376d9e91f194c606c9a45273c170621d46128f35aef7cd0", - "sha256:6ba8858933f0c1a979781272a5f65646fca8c18c93c99c6ddb5513ad96fa54b1", - "sha256:6bc568b05e02cd612be53900c88aaa55012e744930ba2eeb56279db4c6676eb3", - "sha256:729408136ef8d45a28ee9a7411917c9e3459cf266c7e23c2f7d4bb8ef9e0da42", - "sha256:751758d9dd04d548ec679224cc00e3591f5ebf1ff159ed0d4aba6a0746352452", - "sha256:76d59d4d451ba77f08cb4cd9268dec07be5bc65f73666302dbb5061989b17198", - "sha256:79bf58c08f0756adba691d480b5a20e4ad23f33e1ae121584cf3a21717c36dfa", - "sha256:7de12b69d95072394998c622cfd7e8cea8f560db5fca6a62a148f902a1029f8b", - "sha256:7f55cd9cf1564b7b03f238e4c017ca4794c05b01a783e9291065cb2858d86ce4", - "sha256:80e5acb81cb49fd9f2d5c08f8b74ffff14ee73b10ca88297ab4619e946bcb1e1", - "sha256:87a90f5545fd61f6964e65eebde4dc3fa8660bb7d87adb01d4cf17e0a2b484ad", - "sha256:881df98f0a8404d32b6de0fd33e91c1b90ed1516a80d4d6dc69d414b8850474c", - "sha256:8a776a29b77fe0cc28fedfd87277b0d0f7aa930174b7e504d764e0b43a05f381", - "sha256:8c2a61c0e4811012b0ba9f6cdcb4437865df5d29eab5d6018ba13cee1c3064a0", - "sha256:8fa6bd071ec6d90f6e7baa66ae25820d57a8ab1b0a3c6d3edf1834d4b26fafa2", - "sha256:96f2975fb14f39c5fe75203f33dd3010fe37d1c4e33177feef1107b5ced750e3", - "sha256:96fb0899bb2ab353f42e5374c8f0789f54e0a94ef2f02b9ac7149c56622eaf31", - "sha256:97163a1ab265a1073a6372eca9f4eeb9f8c6327457a0b22ddfc4a17dcd613e74", - "sha256:9c95a1a290f9acf7a8f2ebbdd183e99215d491beea52d61aa2a7a7d2c618ddc6", - "sha256:9d94d78418203904730585efa71002286ac4c8ac0689d0eb61e3c465f9e608ff", - "sha256:a6ba2cb7d676e9415b9e9ac7e2aae401dc1b1e666943d1f7bc66223d3d73467b", - "sha256:aa0379c1935c44053c98826bc99ac95f3a5355675a297ac9ce0dfad0ce2d50ca", - "sha256:ac96d67b37f28e4b6ecf507c3405f52a40658c0a806dffde624a8fcb0314d5fd", - "sha256:ade2ccb937060c299ab0dfb2dea3d2ddf7e098ed63ee3d651ebfc2c8d1e8632a", - "sha256:aefbdc934115d2f9278f153952003ac52cd2650e7313750390b334518c589568", - "sha256:b07501b720cf060c5856f7b5626e75b8e353b5f98b9b354a21eb4bfa47e421b1", - "sha256:b5267feb19070bef34b8dea27e2b504ebd9d31748e3ecacb3a4101da6fcb255c", - "sha256:b5f6328e8e2ae8238fc767703ab7b95785521c42bb2b8790984e3477d7fa71ad", - "sha256:b8996ffb60c69f677245f5abdbcc623e9442bcc91ed81b6cd6187129ad1fa3e7", - "sha256:b981a370f8f41c4024c170b42fbe9e691ae2dbc19d1d99151a69e2c84a0d194d", - "sha256:b9d121be0217787a7d59a5c6195b0842d3f701007333426e5154bf72346aa658", - "sha256:bcef4f2d3dc603150421de85c916da19471f24d838c3c62a4f04c1eb511642c1", - "sha256:bed0252c85e21cf73d2d033643c945b460d6a02fc4a7d644e3b2d6f5f2956c64", - "sha256:bfdfbe6a36bc3059fff845d64c42f2644cf875c65f5005db54f90cdfdf1df815", - "sha256:c0095b8aa3e432e32d372e9a7737e65b58d5ed23b9620fea7cb81f17672f1fa1", - "sha256:c1f41d32a2ddc5a94df4b829b395916a4b7f103350fa76ba6de625fcb9e773ac", - "sha256:c45008ca79bad237cbc03c72bc5205e8c6f66403773929b1b50f7d84ef9e4d07", - "sha256:c82bbf7e03748417c3a88c1b0b291288ce3e4887a795a3addaa7a1cfd9e7153e", - "sha256:c918621ee0a3d1fe61c313f2489464f2ae3d13633e60f520a8002a5e910982ee", - "sha256:d204957169f0b3511fb95395a9da7d4490fb361763a9f8b32b345a7fe119cb45", - "sha256:d329896c40d9e1e5c7715c98529e4a188a1f2df51212fd65102b32465612b5dc", - "sha256:d3a61e928feddc458a55110f42f626a2a20bea942ccedb6fb4cee70b4830ed41", - "sha256:d48db29bd47814671afdd76c7652aefacc25cf96aad6daefa82d738ee87461e2", - "sha256:d5593855b5b2b73dd8413c3fdfa5d95b99d657658f947ba2c4318591e745d083", - "sha256:d79c159adea0f1f4617f54aa156568ac69968f9ef4d1e5fefffc0a180830308e", - "sha256:db09b98c7540df69d4b47218da3fbd7cb466db0fb932e971c321f1c76f155266", - "sha256:ddf23960cb42b69bce13045d5bc66f18c7d53774c66c13f24cf1b9c144ba3141", - "sha256:e06cfea0ece444571d24c18ed465bc93afb8c8d8d74422eb7026662f3d3f779b", - "sha256:e7c564c58cf8f248fe859a4f0fe501b050663f3d7fbc342172f259124fb59933", - "sha256:e86593bf8637659e6a6ed58854b6c87ec4e9e45ee8a4adfd936831cef55c2d21", - "sha256:eaffbd8814bb1b5dc3ea156a4c5928081ba50419f9175f4fc95269e040eff8f0", - "sha256:ee353bb51f648924926ed05e0122b6a0b1ae709396a80eb583449d5d477fcdf7", - "sha256:ee6faebb265e28920a6f23a7d4c362414b3f4bb30607141d718b991669e49ddc", - "sha256:efe093acc43e869348f6f2224df7f452eab63a2c60a6c6cd6b50fd35c4e075ba", - "sha256:f03a1b3a4c03e3e0161642ac5367f08479ab29972ea0ffcd4fa18f729cd2be0a", - "sha256:f0d320e70b6b2300ff6029e234e79fe44e9dbbfc7b98597ba28e054bd6606a57", - "sha256:f252dfb4852a527987a9156cbcae3022a30f86c9d26f4f17b8c967d7580d65d2", - "sha256:f5f4424cb87a20b016bfdc157ff48757b89d2cc426256961643d443c6c277007", - "sha256:f8eae66a1304de7368932b42d801c67969fd090ddb1a7a24f27b435ed4bed68f", - "sha256:fdb82eb60d31b0c033a8e8ee9f3fc7dfbaa042211131c29da29aea8531b4f18f" + "sha256:05f3d615099bd9b13ecf2fc9cf2d839ad3f20239c678f461c753e93755d629ee", + "sha256:06d218939e1bf2ca50e6b0ec700ffe755e5216a8230ab3e87c059ebb4ea06afc", + "sha256:07f2139741e5deb2c5154a7b9629bc5aa48c766b643c1a6750d16f865a82c5fc", + "sha256:08d74b184f9ab6289b87b19fe6a6d1a97fbfea84b8a3e745e87a5de3029bf944", + "sha256:0abeee75434e2ee2d142d650d1e54ac1f8b01e6e6abdde8ffd6eeac6e9c38e20", + "sha256:154bf5c93d79558b44e5b50cc354aa0459e518e83677791e6adb0b039b7aa6a7", + "sha256:17c6d2155e2423f7e79e3bb18151c686d40db42d8645e7977442170c360194d4", + "sha256:1805d5901779662d599d0e2e4159d8a82c0b05faa86ef9222bf974572286b2b6", + "sha256:19ba472b9606c36716062c023afa2484d1e4220548751bda14f725a7de17b4f6", + "sha256:19e515b78c3fc1039dd7da0a33c28c3154458f947f4dc198d3c72db2b6b5dc93", + "sha256:1d54f74f40b1f7aaa595a02ff42ef38ca654b1469bef7d52867da474243cc633", + "sha256:207c82978115baa1fd8d706d720b4a4d2b0913df1c78c85ba73fe6c5804505f0", + "sha256:2625f03b105328729f9450c8badda34d5243231eef6535f80064d57035738360", + "sha256:27bba383e8c5231cd559affe169ca0b96ec78d39909ffd817f28b166d7ddd4d8", + "sha256:2c3caec4ec5cd1d18e5dd6ae5194d24ed12785212a90b37f5f7f06b8bedd7139", + "sha256:2cc7c1a47f3a63282ab0f422d90ddac4aa3034e39fc66a559ab93041e6505da7", + "sha256:2fc24a329a717f9e2448f8cd1f960f9dac4e45b6224d60734edeb67499bab03a", + "sha256:312fe69b4fe1ffbe76520a7676b1e5ac06ddf7826d764cc10265c3b53f96dbe9", + "sha256:32b7daaa3e9389db3695964ce8e566e3413b0c43e3394c05e4b243a4cd7bef26", + "sha256:338dee44b0cef8b70fd2ef54b4e09bb1b97fc6c3a58fea5db6cc083fd9fc2724", + "sha256:352a88dc7892f1da66b6027af06a2e7e5d53fe05924cc2cfc56495b586a10b72", + "sha256:35b2b771b13eee8729a5049c976197ff58a27a3829c018a04341bcf1ae409b2b", + "sha256:38e14fb4e370885c4ecd734f093a2225ee52dc384b86fa55fe3f74638b2cfb09", + "sha256:3c20f05e8e3d4fc76875fc9cb8cf24b90a63f5a1b4c5b9273f0e8225e169b100", + "sha256:3dd3cd86e1db5aadd334e011eba4e29d37a104b403e8ca24dcd6703c68ca55b3", + "sha256:489bdfe1abd0406eba6b3bb4fdc87c7fa40f1031de073d0cfb744634cc8fa261", + "sha256:48c2faaa8adfacefcbfdb5f2e2e7bdad081e5ace8d182e5f4ade971f128e6bb3", + "sha256:4a98a1f0552b5f227a3d6422dbd61bc6f30db170939bd87ed14f3c339aa6c7c9", + "sha256:4adec039b8e2928983f885c53b7cc4cda8965b62b6596501a0308d2703f8af1b", + "sha256:4e0ee01ad8260184db21468a6e1c37afa0529acc12c3a697ee498d3c2c4dcaf3", + "sha256:51584acc5916212e1bf45edd17f3a6b05fe0cbb40482d25e619f824dccb679de", + "sha256:531796fb842b53f2695e94dc338929e9f9dbf473b64710c28af5a160b2a8927d", + "sha256:5463c47c08630007dc0fe99fb480ea4f34a89712410592380425a9b4e1611d8e", + "sha256:5c45a639e93a0c5d4b788b2613bd637468edd62f8f95ebc6fcc303d58ab3f0a8", + "sha256:6031b25fb1b06327b43d841f33842b383beba399884f8228a6bb3df3088485ff", + "sha256:607345bd5912aacc0c5a63d45a1f73fef29e697884f7e861094e443187c02be5", + "sha256:618916f5535784960f3ecf8111581f4ad31d347c3de66d02e728de460a46303c", + "sha256:636a15acc588f70fda1661234761f9ed9ad79ebed3f2125d44be0862708b666e", + "sha256:673fdbbf668dd958eff750e500495ef3f611e2ecc209464f661bc82e9838991e", + "sha256:6afd80f6c79893cfc0574956f78a0add8c76e3696f2d6a15bca2c66c415cf2d4", + "sha256:6b5ff7e1d63a8281654b5e2896d7f08799378e594f09cf3674e832ecaf396ce8", + "sha256:6c4c4c3f878df21faf5fac86eda32671c27889e13570645a9eea0a1abdd50922", + "sha256:6cd8098517c64a85e790657e7b1e509b9fe07487fd358e19431cb120f7d96338", + "sha256:6d1e42d2735d437e7e80bab4d78eb2e459af48c0a46e686ea35f690b93db792d", + "sha256:6e30ac5e329098903262dc5bdd7e2086e0256aa762cc8b744f9e7bf2a427d3f8", + "sha256:70a838f7754483bcdc830444952fd89645569e7452e3226de4a613a4c1793fb2", + "sha256:720edcb916df872d80f80a1cc5ea9058300b97721efda8651efcd938a9c70a72", + "sha256:732672fbc449bab754e0b15356c077cc31566df874964d4801ab14f71951ea80", + "sha256:740884bc62a5e2bbb31e584f5d23b32320fd75d79f916f15a788d527a5e83644", + "sha256:7700936ef9d006b7ef605dc53aa364da2de5a3aa65516a1f3ce73bf82ecfc7ae", + "sha256:7732770412bab81c5a9f6d20aeb60ae943a9b36dcd990d876a773526468e7163", + "sha256:7750569d9526199c5b97e5a9f8d96a13300950d910cf04a861d96f4273d5b104", + "sha256:7f1944ce16401aad1e3f7d312247b3d5de7981f634dc9dfe90da72b87d37887d", + "sha256:81c5196a790032e0fc2464c0b4ab95f8610f96f1f2fa3d4deacce6a79852da60", + "sha256:8352f48d511de5f973e4f2f9412736d7dea76c69faa6d36bcf885b50c758ab9a", + "sha256:8927638a4d4137a289e41d0fd631551e89fa346d6dbcfc31ad627557d03ceb6d", + "sha256:8c7672e9fba7425f79019db9945b16e308ed8bc89348c23d955c8c0540da0a07", + "sha256:8d2e182c9ee01135e11e9676e9a62dfad791a7a467738f06726872374a83db49", + "sha256:910e71711d1055b2768181efa0a17537b2622afeb0424116619817007f8a2b10", + "sha256:942695a206a58d2575033ff1e42b12b2aece98d6003c6bc739fbf33d1773b12f", + "sha256:9437ca26784120a279f3137ee080b0e717012c42921eb07861b412340f85bae2", + "sha256:967342e045564cef76dfcf1edb700b1e20838d83b1aa02ab313e6a497cf923b8", + "sha256:998125738de0158f088aef3cb264a34251908dd2e5d9966774fdab7402edfab7", + "sha256:9e6934d70dc50f9f8ea47081ceafdec09245fd9f6032669c3b45705dea096b88", + "sha256:a3d456ff2a6a4d2adcdf3c1c960a36f4fd2fec6e3b4902a42a384d17cf4e7a65", + "sha256:a7b28c5b066bca9a4eb4e2f2663012debe680f097979d880657f00e1c30875a0", + "sha256:a888e8bdb45916234b99da2d859566f1e8a1d2275a801bb8e4a9644e3c7e7909", + "sha256:aa3679e751408d75a0b4d8d26d6647b6d9326f5e35c00a7ccd82b78ef64f65f8", + "sha256:aaa71ee43a703c321906813bb252f69524f02aa05bf4eec85f0c41d5d62d0f4c", + "sha256:b646bf655b135ccf4522ed43d6902af37d3f5dbcf0da66c769a2b3938b9d8184", + "sha256:b906b5f58892813e5ba5c6056d6a5ad08f358ba49f046d910ad992196ea61397", + "sha256:b9bb1f182a97880f6078283b3505a707057c42bf55d8fca604f70dedfdc0772a", + "sha256:bd1105b50ede37461c1d51b9698c4f4be6e13e69a908ab7751e3807985fc0346", + "sha256:bf18932d0003c8c4d51a39f244231986ab23ee057d235a12b2684ea26a353590", + "sha256:c273e795e7a0f1fddd46e1e3cb8be15634c29ae8ff31c196debb620e1edb9333", + "sha256:c69882964516dc143083d3795cb508e806b09fc3800fd0d4cddc1df6c36e76bb", + "sha256:c827576e2fa017a081346dce87d532a5310241648eb3700af9a571a6e9fc7e74", + "sha256:cbfbea39ba64f5e53ae2915de36f130588bba71245b418060ec3330ebf85678e", + "sha256:ce0bb20e3a11bd04461324a6a798af34d503f8d6f1aa3d2aa8901ceaf039176d", + "sha256:d0cee71bc618cd93716f3c1bf56653740d2d13ddbd47673efa8bf41435a60daa", + "sha256:d21be4770ff4e08698e1e8e0bce06edb6ea0626e7c8f560bc08222880aca6a6f", + "sha256:d31dea506d718693b6b2cffc0648a8929bdc51c70a311b2770f09611caa10d53", + "sha256:d44607f98caa2961bab4fa3c4309724b185b464cdc3ba6f3d7340bac3ec97cc1", + "sha256:d58ad6317d188c43750cb76e9deacf6051d0f884d87dc6518e0280438648a9ac", + "sha256:d70129cef4a8d979caa37e7fe957202e7eee8ea02c5e16455bc9808a59c6b2f0", + "sha256:d85164315bd68c0806768dc6bb0429c6f95c354f87485ee3593c4f6b14def2bd", + "sha256:d960de62227635d2e61068f42a6cb6aae91a7fe00fca0e3aeed17667c8a34611", + "sha256:dc48b479d540770c811fbd1eb9ba2bb66951863e448efec2e2c102625328e92f", + "sha256:e1735502458621921cee039c47318cb90b51d532c2766593be6207eec53e5c4c", + "sha256:e2be6e9dd4111d5b31ba3b74d17da54a8319d8168890fbaea4b9e5c3de630ae5", + "sha256:e4c39ad2f512b4041343ea3c7894339e4ca7839ac38ca83d68a832fc8b3748ab", + "sha256:ed402d6153c5d519a0faf1bb69898e97fb31613b49da27a84a13935ea9164dfc", + "sha256:ee17cd26b97d537af8f33635ef38be873073d516fd425e80559f4585a7b90c43", + "sha256:f3027be483868c99b4985fda802a57a67fdf30c5d9a50338d9db646d590198da", + "sha256:f5bab211605d91db0e2995a17b5c6ee5edec1270e46223e513eaa20da20076ac", + "sha256:f6f8e3fecca256fefc91bb6765a693d96692459d7d4c644660a9fff32e517843", + "sha256:f7afbfee1157e0f9376c00bb232e80a60e59ed716e3211a80cb8506550671e6e", + "sha256:fa242ac1ff583e4ec7771141606aafc92b361cd90a05c30d93e343a0c2d82a89", + "sha256:fab6ce90574645a0d6c58890e9bcaac8d94dff54fb51c69e5522a7358b80ab64" ], "markers": "python_version >= '3.8'", - "version": "==0.13.2" + "version": "==0.18.1" }, "setuptools": { "hashes": [ - "sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2", - "sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6" + "sha256:6c1fccdac05a97e598fb0ae3bbed5904ccb317337a51139dcd51453611bbb987", + "sha256:c636ac361bc47580504644275c9ad802c50415c7522212252c033bd15f301f32" ], "markers": "python_version >= '3.8'", - "version": "==69.0.2" + "version": "==69.5.1" }, "six": { "hashes": [ @@ -1507,18 +1669,18 @@ }, "sphinx": { "hashes": [ - "sha256:1e09160a40b956dc623c910118fa636da93bd3ca0b9876a7b3df90f07d691560", - "sha256:9a5160e1ea90688d5963ba09a2dcd8bdd526620edbb65c328728f1b2228d5ab5" + "sha256:413f75440be4cacf328f580b4274ada4565fb2187d696a84970c23f77b64d8c3", + "sha256:a4a7db75ed37531c05002d56ed6948d4c42f473a36f46e1382b0bd76ca9627bc" ], "markers": "python_version >= '3.9'", - "version": "==7.2.6" + "version": "==7.3.7" }, "sphinx-autodoc-typehints": { "hashes": [ - "sha256:3cabc2537e17989b2f92e64a399425c4c8bf561ed73f087bc7414a5003616a50", - "sha256:5ed05017d23ad4b937eab3bee9fae9ab0dd63f0b42aa360031f1fad47e47f673" + "sha256:70db10b391acf4e772019765991d2de0ff30ec0899b9ba137706dc0b3c4835e0", + "sha256:d3da7fa9a9761eff6ff09f8b1956ae3090a2d4f4ad54aebcade8e458d6340835" ], - "version": "==1.25.2" + "version": "==1.25.3" }, "sphinx-rtd-theme": { "hashes": [ @@ -1529,27 +1691,27 @@ }, "sphinxcontrib-applehelp": { "hashes": [ - "sha256:094c4d56209d1734e7d252f6e0b3ccc090bd52ee56807a5d9315b19c122ab15d", - "sha256:39fdc8d762d33b01a7d8f026a3b7d71563ea3b72787d5f00ad8465bd9d6dfbfa" + "sha256:c40a4f96f3776c4393d933412053962fac2b84f4c99a7982ba42e09576a70619", + "sha256:cb61eb0ec1b61f349e5cc36b2028e9e7ca765be05e49641c97241274753067b4" ], "markers": "python_version >= '3.9'", - "version": "==1.0.7" + "version": "==1.0.8" }, "sphinxcontrib-devhelp": { "hashes": [ - "sha256:63b41e0d38207ca40ebbeabcf4d8e51f76c03e78cd61abe118cf4435c73d4212", - "sha256:fe8009aed765188f08fcaadbb3ea0d90ce8ae2d76710b7e29ea7d047177dae2f" + "sha256:6485d09629944511c893fa11355bda18b742b83a2b181f9a009f7e500595c90f", + "sha256:9893fd3f90506bc4b97bdb977ceb8fbd823989f4316b28c3841ec128544372d3" ], "markers": "python_version >= '3.9'", - "version": "==1.0.5" + "version": "==1.0.6" }, "sphinxcontrib-htmlhelp": { "hashes": [ - "sha256:6c26a118a05b76000738429b724a0568dbde5b72391a688577da08f11891092a", - "sha256:8001661c077a73c29beaf4a79968d0726103c5605e27db92b9ebed8bab1359e9" + "sha256:0dc87637d5de53dd5eec3a6a01753b1ccf99494bd756aafecd74b4fa9e729015", + "sha256:393f04f112b4d2f53d93448d4bce35842f62b307ccdc549ec1585e950bc35e04" ], "markers": "python_version >= '3.9'", - "version": "==2.0.4" + "version": "==2.0.5" }, "sphinxcontrib-jquery": { "hashes": [ @@ -1569,19 +1731,19 @@ }, "sphinxcontrib-qthelp": { "hashes": [ - "sha256:62b9d1a186ab7f5ee3356d906f648cacb7a6bdb94d201ee7adf26db55092982d", - "sha256:bf76886ee7470b934e363da7a954ea2825650013d367728588732c7350f49ea4" + "sha256:053dedc38823a80a7209a80860b16b722e9e0209e32fea98c90e4e6624588ed6", + "sha256:e2ae3b5c492d58fcbd73281fbd27e34b8393ec34a073c792642cd8e529288182" ], "markers": "python_version >= '3.9'", - "version": "==1.0.6" + "version": "==1.0.7" }, "sphinxcontrib-serializinghtml": { "hashes": [ - "sha256:0c64ff898339e1fac29abd2bf5f11078f3ec413cfe9c046d3120d7ca65530b54", - "sha256:9b36e503703ff04f20e9675771df105e58aa029cfcbc23b8ed716019b7416ae1" + "sha256:326369b8df80a7d2d8d7f99aa5ac577f51ea51556ed974e7716cfd4fca3f6cb7", + "sha256:93f3f5dc458b91b192fe10c397e324f262cf163d79f3282c158e8436a2c4511f" ], "markers": "python_version >= '3.9'", - "version": "==1.1.9" + "version": "==1.1.10" }, "stack-data": { "hashes": [ @@ -1592,11 +1754,11 @@ }, "synapseclient": { "hashes": [ - "sha256:dc5a61f9f495109a0c89aa7d42b641b6ff278280d7961fb450dd5015704fe15b", - "sha256:dd8b1a1b4667d08311bb651469431f43fe2eeab83c0ef1fe5a03c2929aeb26cd" + "sha256:5261a2751ea5757750e0cb2e481ecb2761954e2c0969e7cc5dd1dfff43c3ddcc", + "sha256:c5e0ac45faed1aa618cd66a0f50bf1a8149a2902a71d07487a0e470250955083" ], - "markers": "python_version >= '3.7'", - "version": "==2.7.2" + "markers": "python_version >= '3.8'", + "version": "==4.1.1" }, "tabulate": { "hashes": [ @@ -1606,14 +1768,6 @@ "markers": "python_version >= '3.7'", "version": "==0.9.0" }, - "toml": { - "hashes": [ - "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", - "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" - ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'", - "version": "==0.10.2" - }, "tornado": { "hashes": [ "sha256:02ccefc7d8211e5a7f9e8bc3f9e5b0ad6262ba2fbb683a6443ecc804e5224ce0", @@ -1633,11 +1787,11 @@ }, "traitlets": { "hashes": [ - "sha256:f14949d23829023013c47df20b4a76ccd1a85effb786dc060f34de7948361b33", - "sha256:fcdaa8ac49c04dfa0ed3ee3384ef6dfdb5d6f3741502be247279407679296772" + "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", + "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f" ], "markers": "python_version >= '3.8'", - "version": "==5.14.0" + "version": "==5.14.3" }, "typer": { "hashes": [ @@ -1649,11 +1803,11 @@ }, "typing-extensions": { "hashes": [ - "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783", - "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd" + "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0", + "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a" ], "markers": "python_version >= '3.8'", - "version": "==4.9.0" + "version": "==4.11.0" }, "urllib3": { "hashes": [ @@ -1665,26 +1819,26 @@ }, "virtualenv": { "hashes": [ - "sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3", - "sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b" + "sha256:604bfdceaeece392802e6ae48e69cec49168b9c5f4a44e483963f9242eb0e78b", + "sha256:7aa9982a728ae5892558bff6a2839c00b9ed145523ece2274fad6f414690ae75" ], "markers": "python_version >= '3.7'", - "version": "==20.25.0" + "version": "==20.26.1" }, "wcwidth": { "hashes": [ - "sha256:f01c104efdf57971bcb756f054dd58ddec5204dd15fa31d6503ea57947d97c02", - "sha256:f26ec43d96c8cbfed76a5075dac87680124fa84e0855195a6184da9c187f133c" + "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", + "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5" ], - "version": "==0.2.12" + "version": "==0.2.13" }, "websocket-client": { "hashes": [ - "sha256:10e511ea3a8c744631d3bd77e61eb17ed09304c413ad42cf6ddfa4c7787e8fe6", - "sha256:f4c3d22fec12a2461427a29957ff07d35098ee2d976d3ba244e688b8b4057588" + "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526", + "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da" ], "markers": "python_version >= '3.8'", - "version": "==1.7.0" + "version": "==1.8.0" }, "wrapt": { "hashes": [ @@ -1764,11 +1918,11 @@ }, "zipp": { "hashes": [ - "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31", - "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0" + "sha256:206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b", + "sha256:2884ed22e7d8961de1c9a05142eb69a247f120291bc0206a00a7642f09b5b715" ], "markers": "python_version >= '3.8'", - "version": "==3.17.0" + "version": "==3.18.1" } } } diff --git a/setup.cfg b/setup.cfg index 1218dfa..73d9001 100644 --- a/setup.cfg +++ b/setup.cfg @@ -51,7 +51,7 @@ python_requires = >=3.9, <3.12 # Updates here should be reflected in `docs/requirements.txt` install_requires = fs~=2.4 - fs-synapse~=1.0 + fs-synapse~=2.0 typer~=0.7.0 [options.packages.find] From d922437c11a08d817fedd1dedebb2b9dd105e4b5 Mon Sep 17 00:00:00 2001 From: bwmac Date: Tue, 7 May 2024 10:15:21 -0600 Subject: [PATCH 05/30] updates updater for exposing dcqc result details --- src/dcqc/updaters.py | 45 ++++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/src/dcqc/updaters.py b/src/dcqc/updaters.py index 4233e92..5fd2101 100644 --- a/src/dcqc/updaters.py +++ b/src/dcqc/updaters.py @@ -6,6 +6,7 @@ from dcqc.parsers import CsvParser from dcqc.suites.suite_abc import SuiteABC +from dcqc.tests.base_test import TestStatus @dataclass @@ -19,31 +20,39 @@ def __init__(self, input_path: Path, output_path: Path): self.input_path = input_path def update(self, suites: List[SuiteABC]): - suite_dict = defaultdict(list) - # {url: [list_of_statuses]} data structure to allow for multi-file targets + suite_dict = {} # TODO add support for suites with multiple files in them (multi) for suite in suites: url = suite.target.files[0].url - status = suite.get_status() - suite_dict[url].append(status.value) - # Evaluate dcqc_status for each url - collapsed_dict = {} - for url, statuses in suite_dict.items(): - if "GREY" in statuses: - collapsed_dict[url] = "GREY" - elif "RED" in statuses: - collapsed_dict[url] = "RED" - elif "AMBER" in statuses: - collapsed_dict[url] = "AMBER" - elif "GREEN" in statuses: - collapsed_dict[url] = "GREEN" - else: - collapsed_dict[url] = "NONE" + suite_dict[url] = { + "status": suite.get_status().value, + "required_tests": suite.required_tests, + "skipped_tests": suite.skipped_tests, + "failed_tests": [], + "errored_tests": [], + } + for test in suite.tests: + if test._status == TestStatus.FAIL: + suite_dict[url]["failed_tests"].append(test.type) + if test._status == TestStatus.ERROR: + suite_dict[url]["errored_tests"].append(test.type) # Create CSV data structure row_list = [] parser = CsvParser(self.input_path) for _, csv_data in parser.list_rows(): - csv_data["dcqc_status"] = collapsed_dict[csv_data["url"]] + csv_data["dcqc_status"] = suite_dict[csv_data["url"]]["status"] + csv_data["dcqc_required_tests"] = ",".join( + suite_dict[csv_data["url"]]["required_tests"] + ) + csv_data["dcqc_skipped_tests"] = ",".join( + suite_dict[csv_data["url"]]["skipped_tests"] + ) + csv_data["dcqc_failed_tests"] = ",".join( + suite_dict[csv_data["url"]]["failed_tests"] + ) + csv_data["dcqc_errored_tests"] = ",".join( + suite_dict[csv_data["url"]]["errored_tests"] + ) row_list.append(csv_data) if row_list: From 0aaba301c72c5c63c23ad91988062df2a5e19dee Mon Sep 17 00:00:00 2001 From: bwmac Date: Tue, 7 May 2024 12:53:27 -0600 Subject: [PATCH 06/30] updates md5 and file extensions teests --- src/dcqc/suites/suites.py | 4 +--- src/dcqc/tests/file_extension_test.py | 1 + src/dcqc/tests/md5_checksum_test.py | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dcqc/suites/suites.py b/src/dcqc/suites/suites.py index 437b2ca..3e792da 100644 --- a/src/dcqc/suites/suites.py +++ b/src/dcqc/suites/suites.py @@ -3,11 +3,9 @@ from dcqc.suites.suite_abc import SuiteABC -# TODO: Consider moving the filetype-test association logic -# to the file types class FileSuite(SuiteABC): file_type = FileType.get_file_type("*") - # add_tests = (tests.FileExtensionTest, tests.Md5ChecksumTest) + add_tests = (tests.FileExtensionTest, tests.Md5ChecksumTest) class JsonSuite(FileSuite): diff --git a/src/dcqc/tests/file_extension_test.py b/src/dcqc/tests/file_extension_test.py index b6206c8..c5fafae 100644 --- a/src/dcqc/tests/file_extension_test.py +++ b/src/dcqc/tests/file_extension_test.py @@ -13,5 +13,6 @@ def compute_status(self) -> TestStatus: file_extensions = file_type.file_extensions if not file.name.endswith(file_extensions): status = TestStatus.FAIL + self.failure_reason = f"{file.name} does not have one of the expected extensions ({file_extensions}) for file type: {file_type.name}" break return status diff --git a/src/dcqc/tests/md5_checksum_test.py b/src/dcqc/tests/md5_checksum_test.py index 3a76f16..d009750 100644 --- a/src/dcqc/tests/md5_checksum_test.py +++ b/src/dcqc/tests/md5_checksum_test.py @@ -17,6 +17,7 @@ def compute_status(self) -> TestStatus: status = TestStatus.PASS else: status = TestStatus.FAIL + self.failure_reason = "Actual MD5 does not match provided value" return status def _compute_md5_checksum(self, path: Path) -> str: From ce6279145d3600d89e469f720cd77de5a674f6ea Mon Sep 17 00:00:00 2001 From: bwmac Date: Tue, 7 May 2024 13:30:14 -0600 Subject: [PATCH 07/30] updates rest of internal tests --- src/dcqc/tests/json_load_test.py | 1 + src/dcqc/tests/jsonld_load_test.py | 1 + src/dcqc/tests/md5_checksum_test.py | 2 +- src/dcqc/tests/paired_fastq_parity_test.py | 2 ++ 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/dcqc/tests/json_load_test.py b/src/dcqc/tests/json_load_test.py index b31ee5b..ddb49b7 100644 --- a/src/dcqc/tests/json_load_test.py +++ b/src/dcqc/tests/json_load_test.py @@ -15,6 +15,7 @@ def compute_status(self) -> TestStatus: status = TestStatus.PASS else: status = TestStatus.FAIL + self.failure_reason = "File content is unable to be loaded as JSON" return status def _can_be_loaded(self, path: Path) -> bool: diff --git a/src/dcqc/tests/jsonld_load_test.py b/src/dcqc/tests/jsonld_load_test.py index ad9e959..6a6877e 100644 --- a/src/dcqc/tests/jsonld_load_test.py +++ b/src/dcqc/tests/jsonld_load_test.py @@ -14,6 +14,7 @@ def compute_status(self) -> TestStatus: status = TestStatus.PASS else: status = TestStatus.FAIL + self.failure_reason = "File content is unable to be loaded as JSON-LD" return status def _can_be_loaded(self, path: Path) -> bool: diff --git a/src/dcqc/tests/md5_checksum_test.py b/src/dcqc/tests/md5_checksum_test.py index d009750..35a0e43 100644 --- a/src/dcqc/tests/md5_checksum_test.py +++ b/src/dcqc/tests/md5_checksum_test.py @@ -17,7 +17,7 @@ def compute_status(self) -> TestStatus: status = TestStatus.PASS else: status = TestStatus.FAIL - self.failure_reason = "Actual MD5 does not match provided value" + self.failure_reason = "Computed MD5 checksum does not match provided value" return status def _compute_md5_checksum(self, path: Path) -> str: diff --git a/src/dcqc/tests/paired_fastq_parity_test.py b/src/dcqc/tests/paired_fastq_parity_test.py index 3e9f85e..b8dec3b 100644 --- a/src/dcqc/tests/paired_fastq_parity_test.py +++ b/src/dcqc/tests/paired_fastq_parity_test.py @@ -18,6 +18,7 @@ def compute_status(self) -> TestStatus: try: count = self._count_fastq_lines(path) except Exception: + self.failure_reason = "Unable to count FASTQ lines" return TestStatus.FAIL counts.append(count) @@ -26,6 +27,7 @@ def compute_status(self) -> TestStatus: status = TestStatus.PASS else: status = TestStatus.FAIL + self.failure_reason = "FASTQ files do not have the same number of lines" return status def _count_fastq_lines(self, path: Path) -> int: From 2dceb89d4d71646318f0b0654e4711b7d739f3eb Mon Sep 17 00:00:00 2001 From: bwmac Date: Tue, 7 May 2024 13:59:15 -0600 Subject: [PATCH 08/30] Updates testing for internal tests --- src/dcqc/tests/file_extension_test.py | 4 +++- tests/test_internal_tests.py | 31 +++++++++++++++++++++++---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/dcqc/tests/file_extension_test.py b/src/dcqc/tests/file_extension_test.py index c5fafae..a9e87c9 100644 --- a/src/dcqc/tests/file_extension_test.py +++ b/src/dcqc/tests/file_extension_test.py @@ -13,6 +13,8 @@ def compute_status(self) -> TestStatus: file_extensions = file_type.file_extensions if not file.name.endswith(file_extensions): status = TestStatus.FAIL - self.failure_reason = f"{file.name} does not have one of the expected extensions ({file_extensions}) for file type: {file_type.name}" + self.failure_reason = ( + f"File extension does not match one of: {file_extensions}" + ) break return status diff --git a/tests/test_internal_tests.py b/tests/test_internal_tests.py index 9fc5603..2b8f827 100644 --- a/tests/test_internal_tests.py +++ b/tests/test_internal_tests.py @@ -52,6 +52,10 @@ def test_that_a_tiff_file_with_good_extensions_is_passed(self): def test_that_the_file_extension_test_works_on_incorrect_files(self): assert self.bad_txt_test.get_status() == TestStatus.FAIL + assert ( + self.bad_txt_test.failure_reason + == f"File extension does not match one of: {self.bad_txt_target.get_file_type().file_extensions}" + ) class Md5ChecksumTest: @@ -67,6 +71,10 @@ def test_that_the_md5_checksum_test_works_on_a_correct_file(self): def test_that_the_md5_checksum_test_works_on_incorrect_files(self): assert self.bad_txt_test.get_status() == TestStatus.FAIL + assert ( + self.bad_txt_test.failure_reason + == "Computed MD5 checksum does not match provided value" + ) class TestJsonLoadTest: @@ -82,6 +90,10 @@ def test_that_the_json_load_test_works_on_a_correct_file(self): def test_that_the_json_load_test_works_on_incorrect_files(self): assert self.good_txt_test.get_status() == TestStatus.FAIL + assert ( + self.good_txt_test.failure_reason + == "File content is unable to be loaded as JSON" + ) class TestJsonLdLoadTest: @@ -97,6 +109,10 @@ def test_that_the_jsonld_load_test_works_on_a_correct_file(self): def test_that_the_jsonld_load_test_works_on_incorrect_files(self): assert self.good_txt_test.get_status() == TestStatus.FAIL + assert ( + self.good_txt_test.failure_reason + == "File content is unable to be loaded as JSON-LD" + ) class TestPairedFastqParityTest: @@ -104,6 +120,7 @@ class TestPairedFastqParityTest: def setup_method(self, test_files): self.fastq1_file = test_files["good_fastq"] self.fastq2_file = test_files["good_compressed_fastq"] + self.good_txt_file = test_files["good_txt"] self.good_paired_target = PairedTarget([self.fastq1_file, self.fastq1_file]) self.good_paired_test = tests.PairedFastqParityTest(self.good_paired_target) self.bad_paired_target = PairedTarget([self.fastq1_file, self.fastq2_file]) @@ -114,18 +131,24 @@ def setup_method(self, test_files): self.good_compressed_paired_test = tests.PairedFastqParityTest( self.good_compressed_paired_target ) + self.good_txt_target = PairedTarget([self.good_txt_file, self.good_txt_file]) + self.good_txt_test = tests.PairedFastqParityTest(self.good_txt_target) def test_that_paired_fastq_parity_test_correctly_passes_identical_fastq_files( self, ): assert self.good_paired_test.get_status() == TestStatus.PASS - def test_that_paired_fastq_parity_test_correctly_fails_different_fastq_files( + def test_that_paired_fastq_parity_test_correctly_handles_compressed_fastq_files( self, ): - assert self.bad_paired_test.get_status() == TestStatus.FAIL + assert self.good_compressed_paired_test.get_status() == TestStatus.PASS - def test_that_paired_fastq_parity_test_correctly_handles_compressed_fastq_files( + def test_that_paired_fastq_parity_test_correctly_fails_different_fastq_files( self, ): - assert self.good_compressed_paired_test.get_status() == TestStatus.PASS + assert self.bad_paired_test.get_status() == TestStatus.FAIL + assert ( + self.bad_paired_test.failure_reason + == "FASTQ files do not have the same number of lines" + ) From 3684937cdff10dff105a86c5c64303d56d62e8e3 Mon Sep 17 00:00:00 2001 From: bwmac Date: Tue, 7 May 2024 15:39:54 -0600 Subject: [PATCH 09/30] adds codes and reasons to external tests --- src/dcqc/tests/bioformats_info_test.py | 4 +++- src/dcqc/tests/libtiff_info_test.py | 4 +++- src/dcqc/tests/ome_xml_schema_test.py | 4 +++- src/dcqc/tests/tiff_date_time_test.py | 4 +++- src/dcqc/tests/tiff_tag_306_date_time_test.py | 4 +++- tests/test_main.py | 1 + 6 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/dcqc/tests/bioformats_info_test.py b/src/dcqc/tests/bioformats_info_test.py index 40144f7..7099efa 100644 --- a/src/dcqc/tests/bioformats_info_test.py +++ b/src/dcqc/tests/bioformats_info_test.py @@ -4,7 +4,9 @@ class BioFormatsInfoTest(ExternalBaseTest): tier = 2 - pass_code = "0" + pass_code = 0 + fail_code = 1 + failure_reason_location = "std_err" target: SingleTarget def generate_process(self) -> Process: diff --git a/src/dcqc/tests/libtiff_info_test.py b/src/dcqc/tests/libtiff_info_test.py index c7d146d..4c9c782 100644 --- a/src/dcqc/tests/libtiff_info_test.py +++ b/src/dcqc/tests/libtiff_info_test.py @@ -4,7 +4,9 @@ class LibTiffInfoTest(ExternalBaseTest): tier = 2 - pass_code = "0" + pass_code = 0 + fail_code = 1 + failure_reason_location = "std_err" target: SingleTarget def generate_process(self) -> Process: diff --git a/src/dcqc/tests/ome_xml_schema_test.py b/src/dcqc/tests/ome_xml_schema_test.py index f8e246a..9df2a31 100644 --- a/src/dcqc/tests/ome_xml_schema_test.py +++ b/src/dcqc/tests/ome_xml_schema_test.py @@ -4,7 +4,9 @@ class OmeXmlSchemaTest(ExternalBaseTest): tier = 2 - pass_code = "0" + pass_code = 0 + fail_code = 1 + failure_reason_location = "std_out" target: SingleTarget def generate_process(self) -> Process: diff --git a/src/dcqc/tests/tiff_date_time_test.py b/src/dcqc/tests/tiff_date_time_test.py index dfeecd9..3cb077b 100644 --- a/src/dcqc/tests/tiff_date_time_test.py +++ b/src/dcqc/tests/tiff_date_time_test.py @@ -4,7 +4,9 @@ class TiffDateTimeTest(ExternalBaseTest): tier = 4 - pass_code = "1" + pass_code = 1 + fail_code = 0 + failure_reason_location = "std_out" target: SingleTarget def generate_process(self) -> Process: diff --git a/src/dcqc/tests/tiff_tag_306_date_time_test.py b/src/dcqc/tests/tiff_tag_306_date_time_test.py index 5ec5d67..a290244 100644 --- a/src/dcqc/tests/tiff_tag_306_date_time_test.py +++ b/src/dcqc/tests/tiff_tag_306_date_time_test.py @@ -4,7 +4,9 @@ class TiffTag306DateTimeTest(ExternalBaseTest): tier = 4 - pass_code = "1" + pass_code = 1 + fail_code = 0 + failure_reason_location = "std_out" target: SingleTarget def generate_process(self) -> Process: diff --git a/tests/test_main.py b/tests/test_main.py index 62e90fe..7e05082 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -69,6 +69,7 @@ def test_create_tests(get_data, get_output): def test_create_process(get_data, get_output): input_json = get_data("test.external.json") + print(input_json) output_path = get_output("create_process") / "process.json" output_path.unlink(missing_ok=True) From 03495684edd3e37704fc3e81ce047eec71c6ddd3 Mon Sep 17 00:00:00 2001 From: bwmac Date: Tue, 7 May 2024 16:17:14 -0600 Subject: [PATCH 10/30] adds reasons to tests.json --- tests/data/tests.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/data/tests.json b/tests/data/tests.json index 21d89de..28bdcec 100644 --- a/tests/data/tests.json +++ b/tests/data/tests.json @@ -4,6 +4,8 @@ "tier": 1, "is_external_test": false, "status": "pending", + "failure_reason": "", + "error_reason": "", "target": { "id": "001", "files": [ @@ -25,6 +27,8 @@ "tier": 2, "is_external_test": true, "status": "pending", + "failure_reason": "", + "error_reason": "", "target": { "id": "001", "files": [ @@ -46,6 +50,8 @@ "tier": 1, "is_external_test": false, "status": "passed", + "failure_reason": "", + "error_reason": "", "target": { "id": "001", "files": [ From 660d7b2d765ab07fc4c55801fc65f6fde23ab4c8 Mon Sep 17 00:00:00 2001 From: bwmac Date: Tue, 7 May 2024 16:25:21 -0600 Subject: [PATCH 11/30] updates output test file --- tests/data/test_output.csv | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/data/test_output.csv b/tests/data/test_output.csv index e37ee65..b27ae39 100644 --- a/tests/data/test_output.csv +++ b/tests/data/test_output.csv @@ -1,5 +1,5 @@ -url,file_type,md5_checksum,dcqc_status -syn://syn51585496,TXT,38b86a456d1f441008986c6f798d5ef9,GREEN -syn://syn51585494,TXT,a542e9b744bedcfd874129ab0f98c4ff,RED -syn://syn51585495,TIFF,38b86a456d1f441008986c6f798d5ef9,AMBER -syn://syn51585493,TIFF,38b86a456d1f441008986c6f798d5ef9,NONE +url,file_type,md5_checksum,dcqc_status,dcqc_required_tests,dcqc_skipped_tests,dcqc_failed_tests,dcqc_errored_tests +syn://syn51585496,TXT,38b86a456d1f441008986c6f798d5ef9,GREEN,,,, +syn://syn51585494,TXT,a542e9b744bedcfd874129ab0f98c4ff,RED,,,, +syn://syn51585495,TIFF,38b86a456d1f441008986c6f798d5ef9,AMBER,,,, +syn://syn51585493,TIFF,38b86a456d1f441008986c6f798d5ef9,NONE,,,, From c63370829b95d7b7cd76d07cfef024c0641efa3d Mon Sep 17 00:00:00 2001 From: bwmac Date: Tue, 7 May 2024 16:25:40 -0600 Subject: [PATCH 12/30] change un used test in suites --- tests/test_suites.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_suites.py b/tests/test_suites.py index 2cf0348..b030c27 100644 --- a/tests/test_suites.py +++ b/tests/test_suites.py @@ -85,9 +85,9 @@ def test_that_the_default_required_tests_are_only_tiers_1_and_2(test_suites): def test_that_skipped_tests_are_skipped_when_building_suite_from_tests(test_suites): suite = test_suites["good_tiff"] tests = suite.tests - new_suite = SuiteABC.from_tests(tests, skipped_tests=["LibTiffInfoTest"]) - skipped_test_before = suite.tests_by_name["LibTiffInfoTest"] - skipped_test_after = new_suite.tests_by_name["LibTiffInfoTest"] + new_suite = SuiteABC.from_tests(tests, skipped_tests=["TiffDateTimeTest"]) + skipped_test_before = suite.tests_by_name["TiffDateTimeTest"] + skipped_test_after = new_suite.tests_by_name["TiffDateTimeTest"] assert skipped_test_before.get_status(compute_ok=False) != TestStatus.SKIP assert skipped_test_after.get_status(compute_ok=False) == TestStatus.SKIP From fc7d9208d8b7337fb902dc391a9591d79a7df6ab Mon Sep 17 00:00:00 2001 From: bwmac Date: Tue, 7 May 2024 16:41:31 -0600 Subject: [PATCH 13/30] revert suites testing changes --- src/dcqc/suites/suites.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/dcqc/suites/suites.py b/src/dcqc/suites/suites.py index 3e792da..6e73e1b 100644 --- a/src/dcqc/suites/suites.py +++ b/src/dcqc/suites/suites.py @@ -21,9 +21,9 @@ class JsonLdSuite(JsonSuite): class TiffSuite(FileSuite): file_type = FileType.get_file_type("TIFF") add_tests = ( - # tests.LibTiffInfoTest, + tests.LibTiffInfoTest, tests.TiffDateTimeTest, - # tests.TiffTag306DateTimeTest, + tests.TiffTag306DateTimeTest, ) @@ -47,7 +47,6 @@ class FastqSuite(FileSuite): class TXTSuite(FileSuite): file_type = FileType.get_file_type("TXT") - add_tests = (tests.GrepDateTest,) class CSVSuite(FileSuite): From a67eac25720375f280f6eeabdcf158dd1910a723 Mon Sep 17 00:00:00 2001 From: bwmac Date: Tue, 7 May 2024 17:13:08 -0600 Subject: [PATCH 14/30] update test files for test_main.py --- tests/data/suite.json | 8 +++-- tests/data/suites.json | 60 ++++++++++++++++++++++++++--------- tests/data/test.computed.json | 2 ++ tests/data/test.external.json | 2 ++ tests/data/test.internal.json | 2 ++ tests/test_main.py | 1 - 6 files changed, 57 insertions(+), 18 deletions(-) diff --git a/tests/data/suite.json b/tests/data/suite.json index 3f6236d..607e188 100644 --- a/tests/data/suite.json +++ b/tests/data/suite.json @@ -29,13 +29,17 @@ "type": "Md5ChecksumTest", "tier": 1, "is_external_test": false, - "status": "passed" + "status": "passed", + "failure_reason": "", + "error_reason": "" }, { "type": "LibTiffInfoTest", "tier": 2, "is_external_test": true, - "status": "skipped" + "status": "skipped", + "failure_reason": "", + "error_reason": "" } ] } diff --git a/tests/data/suites.json b/tests/data/suites.json index aaf72e4..abc02d4 100644 --- a/tests/data/suites.json +++ b/tests/data/suites.json @@ -30,31 +30,41 @@ "type": "FileExtensionTest", "tier": 1, "is_external_test": false, - "status": "passed" + "status": "passed", + "failure_reason": "", + "error_reason": "" }, { "type": "GrepDateTest", "tier": 4, "is_external_test": true, - "status": "passed" + "status": "passed", + "failure_reason": "", + "error_reason": "" }, { "type": "LibTiffInfoTest", "tier": 2, "is_external_test": true, - "status": "passed" + "status": "passed", + "failure_reason": "", + "error_reason": "" }, { "type": "Md5ChecksumTest", "tier": 1, "is_external_test": false, - "status": "passed" + "status": "passed", + "failure_reason": "", + "error_reason": "" }, { "type": "TiffTag306DateTimeTest", "tier": 4, "is_external_test": true, - "status": "passed" + "status": "passed", + "failure_reason": "", + "error_reason": "" } ] }, @@ -89,31 +99,41 @@ "type": "FileExtensionTest", "tier": 1, "is_external_test": false, - "status": "passed" + "status": "passed", + "failure_reason": "", + "error_reason": "" }, { "type": "GrepDateTest", "tier": 4, "is_external_test": true, - "status": "failed" + "status": "failed", + "failure_reason": "test failed", + "error_reason": "" }, { "type": "LibTiffInfoTest", "tier": 2, "is_external_test": true, - "status": "failed" + "status": "failed", + "failure_reason": "test failed", + "error_reason": "" }, { "type": "Md5ChecksumTest", "tier": 1, "is_external_test": false, - "status": "passed" + "status": "passed", + "failure_reason": "", + "error_reason": "" }, { "type": "TiffTag306DateTimeTest", "tier": 4, "is_external_test": true, - "status": "passed" + "status": "passed", + "failure_reason": "", + "error_reason": "" } ] }, @@ -148,31 +168,41 @@ "type": "FileExtensionTest", "tier": 1, "is_external_test": false, - "status": "passed" + "status": "passed", + "failure_reason": "", + "error_reason": "" }, { "type": "GrepDateTest", "tier": 4, "is_external_test": true, - "status": "passed" + "status": "passed", + "failure_reason": "", + "error_reason": "" }, { "type": "LibTiffInfoTest", "tier": 2, "is_external_test": true, - "status": "passed" + "status": "passed", + "failure_reason": "", + "error_reason": "" }, { "type": "Md5ChecksumTest", "tier": 1, "is_external_test": false, - "status": "passed" + "status": "passed", + "failure_reason": "", + "error_reason": "" }, { "type": "TiffTag306DateTimeTest", "tier": 4, "is_external_test": true, - "status": "failed" + "status": "failed", + "failure_reason": "test failed", + "error_reason": "" } ] } diff --git a/tests/data/test.computed.json b/tests/data/test.computed.json index b1b936a..b3dbb6a 100644 --- a/tests/data/test.computed.json +++ b/tests/data/test.computed.json @@ -3,6 +3,8 @@ "tier": 1, "is_external_test": false, "status": "passed", + "failure_reason": "", + "error_reason": "", "target": { "id": "001", "files": [ diff --git a/tests/data/test.external.json b/tests/data/test.external.json index c127947..32f8911 100644 --- a/tests/data/test.external.json +++ b/tests/data/test.external.json @@ -3,6 +3,8 @@ "tier": 2, "is_external_test": true, "status": "pending", + "failure_reason": "", + "error_reason": "", "target": { "id": "001", "files": [ diff --git a/tests/data/test.internal.json b/tests/data/test.internal.json index 55d91be..7b9bc8d 100644 --- a/tests/data/test.internal.json +++ b/tests/data/test.internal.json @@ -3,6 +3,8 @@ "tier": 1, "is_external_test": false, "status": "pending", + "failure_reason": "", + "error_reason": "", "target": { "id": "001", "files": [ diff --git a/tests/test_main.py b/tests/test_main.py index 7e05082..62e90fe 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -69,7 +69,6 @@ def test_create_tests(get_data, get_output): def test_create_process(get_data, get_output): input_json = get_data("test.external.json") - print(input_json) output_path = get_output("create_process") / "process.json" output_path.unlink(missing_ok=True) From 1bac259cf1c3ff4a5f9123d7a689355b748b5c2e Mon Sep 17 00:00:00 2001 From: bwmac Date: Wed, 8 May 2024 13:28:37 -0600 Subject: [PATCH 15/30] remove my DH tag --- src/docker/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/docker/build.sh b/src/docker/build.sh index 2d6f0cd..a35946c 100644 --- a/src/docker/build.sh +++ b/src/docker/build.sh @@ -8,7 +8,7 @@ TARBALL_PATH=$(ls dist/*.tar.gz) export TARBALL_PATH docker build \ - -t bwmac03570/dcqc \ + -t dcqc \ -f "${SCRIPT_DIR}/Dockerfile" \ --platform linux/amd64 \ --build-arg TARBALL_PATH \ From 9d8118f3c5f2a3abb2acd68b4303acd822664130 Mon Sep 17 00:00:00 2001 From: bwmac Date: Wed, 8 May 2024 15:20:59 -0600 Subject: [PATCH 16/30] update error logic --- src/dcqc/suites/suite_abc.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/dcqc/suites/suite_abc.py b/src/dcqc/suites/suite_abc.py index 4b4a8b2..b19af13 100644 --- a/src/dcqc/suites/suite_abc.py +++ b/src/dcqc/suites/suite_abc.py @@ -225,16 +225,16 @@ def compute_status(self) -> SuiteStatus: for test in self.tests: test_name = test.type test_status = test.get_status() + # if test errors, always return grey immediately if test_status == TestStatus.ERROR: self._status = SuiteStatus.GREY return self._status - if test_name in self.required_tests: - if test_status == TestStatus.FAIL: - self._status = SuiteStatus.RED - return self._status - else: - if test_status == TestStatus.FAIL: - self._status = SuiteStatus.AMBER + # if required test failed, red takes precedence over amber + if test_status == TestStatus.FAIL and test_name in self.required_tests: + self._status = SuiteStatus.RED + # if test failed not required test, amber + if test_status == TestStatus.FAIL and self._status != SuiteStatus.RED: + self._status = SuiteStatus.AMBER return self._status def to_dict(self) -> SerializedObject: From 4d688dc176d21fc5498dd75c59fe8fb5d0c57410 Mon Sep 17 00:00:00 2001 From: bwmac Date: Wed, 8 May 2024 15:48:39 -0600 Subject: [PATCH 17/30] remove process output attributes --- src/dcqc/tests/base_test.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/dcqc/tests/base_test.py b/src/dcqc/tests/base_test.py index 6ca88ed..40d41ea 100644 --- a/src/dcqc/tests/base_test.py +++ b/src/dcqc/tests/base_test.py @@ -167,10 +167,6 @@ class ExternalTestMixin(BaseTest): fail_code: int failure_reason_location: str - process_exit_code: int - process_std_out: str - process_std_err: str - # Class constants STDOUT_PATH: ClassVar[Path] STDOUT_PATH = Path("std_out.txt") From 9971463ce089ebee8e1c78072778877c6a1a307c Mon Sep 17 00:00:00 2001 From: bwmac Date: Wed, 8 May 2024 15:54:27 -0600 Subject: [PATCH 18/30] revert test_suite change --- tests/test_suites.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_suites.py b/tests/test_suites.py index b030c27..2cf0348 100644 --- a/tests/test_suites.py +++ b/tests/test_suites.py @@ -85,9 +85,9 @@ def test_that_the_default_required_tests_are_only_tiers_1_and_2(test_suites): def test_that_skipped_tests_are_skipped_when_building_suite_from_tests(test_suites): suite = test_suites["good_tiff"] tests = suite.tests - new_suite = SuiteABC.from_tests(tests, skipped_tests=["TiffDateTimeTest"]) - skipped_test_before = suite.tests_by_name["TiffDateTimeTest"] - skipped_test_after = new_suite.tests_by_name["TiffDateTimeTest"] + new_suite = SuiteABC.from_tests(tests, skipped_tests=["LibTiffInfoTest"]) + skipped_test_before = suite.tests_by_name["LibTiffInfoTest"] + skipped_test_after = new_suite.tests_by_name["LibTiffInfoTest"] assert skipped_test_before.get_status(compute_ok=False) != TestStatus.SKIP assert skipped_test_after.get_status(compute_ok=False) == TestStatus.SKIP From f0a788d886292299fc4593322be0d5aafa7a296f Mon Sep 17 00:00:00 2001 From: bwmac Date: Wed, 8 May 2024 15:54:34 -0600 Subject: [PATCH 19/30] removes unused import --- src/dcqc/updaters.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/dcqc/updaters.py b/src/dcqc/updaters.py index 5fd2101..c9570b3 100644 --- a/src/dcqc/updaters.py +++ b/src/dcqc/updaters.py @@ -1,4 +1,3 @@ -from collections import defaultdict from csv import DictWriter from dataclasses import dataclass from pathlib import Path From 2142e351df44d1ae748071033847b65b51fe70e7 Mon Sep 17 00:00:00 2001 From: bwmac Date: Wed, 8 May 2024 15:59:46 -0600 Subject: [PATCH 20/30] pre-commit fixes --- src/dcqc/updaters.py | 2 +- tests/test_internal_tests.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dcqc/updaters.py b/src/dcqc/updaters.py index c9570b3..70914e3 100644 --- a/src/dcqc/updaters.py +++ b/src/dcqc/updaters.py @@ -19,7 +19,7 @@ def __init__(self, input_path: Path, output_path: Path): self.input_path = input_path def update(self, suites: List[SuiteABC]): - suite_dict = {} + suite_dict: dict[str, dict] = {} # TODO add support for suites with multiple files in them (multi) for suite in suites: url = suite.target.files[0].url diff --git a/tests/test_internal_tests.py b/tests/test_internal_tests.py index 2b8f827..3253616 100644 --- a/tests/test_internal_tests.py +++ b/tests/test_internal_tests.py @@ -52,9 +52,9 @@ def test_that_a_tiff_file_with_good_extensions_is_passed(self): def test_that_the_file_extension_test_works_on_incorrect_files(self): assert self.bad_txt_test.get_status() == TestStatus.FAIL - assert ( - self.bad_txt_test.failure_reason - == f"File extension does not match one of: {self.bad_txt_target.get_file_type().file_extensions}" + assert self.bad_txt_test.failure_reason == ( + "File extension does not match one of: " + f"{self.bad_txt_target.get_file_type().file_extensions}" ) From 4d7f344abe5083488cebe3ad0f94ae5b4b6e1a0f Mon Sep 17 00:00:00 2001 From: bwmac Date: Thu, 9 May 2024 10:26:19 -0600 Subject: [PATCH 21/30] updates README --- CONTRIBUTING.md | 81 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 21 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3c3bbd1..a8cb560 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -43,18 +43,18 @@ that any documentation update is done in the same way was a code contribution. The documentation is written using [CommonMark] with [MyST] extensions. :::{tip} - Please notice that the [GitHub web interface] provides a quick way of - propose changes in `dcqc`'s files. While this mechanism can - be tricky for normal code contributions, it works perfectly fine for - contributing to the docs, and can be quite handy. - - If you are interested in trying this method out, please navigate to - the `docs` folder in the source [repository], find which file you - would like to propose changes and click in the little pencil icon at the - top, to open [GitHub's code editor]. Once you finish editing the file, - please write a message in the form at the bottom of the page describing - which changes have you made and what are the motivations behind them and - submit your proposal. +Please notice that the [GitHub web interface] provides a quick way of +propose changes in `dcqc`'s files. While this mechanism can +be tricky for normal code contributions, it works perfectly fine for +contributing to the docs, and can be quite handy. + +If you are interested in trying this method out, please navigate to +the `docs` folder in the source [repository], find which file you +would like to propose changes and click in the little pencil icon at the +top, to open [GitHub's code editor]. Once you finish editing the file, +please write a message in the form at the bottom of the page describing +which changes have you made and what are the motivations behind them and +submit your proposal. ::: When working on documentation changes in your local machine, you can @@ -91,7 +91,7 @@ This often provides additional considerations and avoids unnecessary work. 1. Create an user account on GitHub if you do not already have one. -2. Fork the project [repository]: click on the *Fork* button near the top of the +2. Fork the project [repository]: click on the _Fork_ button near the top of the page. This creates a copy of the code under your account on GitHub. 3. Clone this copy to your local disk: @@ -108,7 +108,7 @@ This often provides additional considerations and avoids unnecessary work. ``` to create an isolated virtual environment containing package dependencies, - including those needed for development (*e.g.* testing, documentation). + including those needed for development (_e.g._ testing, documentation). 5. Install [pre-commit] hooks: @@ -186,34 +186,72 @@ This often provides additional considerations and avoids unnecessary work. the PR as a draft first and mark it as ready for review after the feedbacks from the continuous integration (CI) system or any required fixes. -### Special Considerations for Contributing External Tests +### Contributing Internal Tests + +In `py-dcqc`, any test where the primary business logic is executed within the package itself is considered internal. One example is the `Md5ChecksumTest`. + +When contributing an internal test be sure to do the following: + +1. Follow the steps above to set up `py-dcqc` and create your contribution. + +1. Include the following class attributes: + + - `tier`: An `int` value describing the complexity of the test contributed. `tier` values include: + - `1`: File Integrity + - `2`: Internal Conformance + - `3`: External Conformance + - `target`: The target class that the test will be applied to. This value will be `SingleTarget` for individual files and `PairedTarget` for paired files. + +1. Implement the major logic of the test in the `compute_status` method. This should include a condition for returning a `status` of `TestStatus.PASS` when the test conditions are met and `TestStatus.FAIL` when they are not. + - For failing cases be sure to include a line setting the class' `failure_reason` to a helpful string that will tell users why the test failed before returning the `status`. + +### Contributing External Tests In `py-dcqc`, any test where the primary business logic is executed outside of this package itself is considered to be external. One example is the `LibTiffInfoTest`. For these tests, `py-dcqc` is responsible for packaging up a Nextflow process which is then executed in an [nf-dcqc](https://github.com/Sage-Bionetworks-Workflows/nf-dcqc) workflow run. Such tests are not possible to run in `py-dcqc` alone at this time. This makes contributing, testing, debugging, and using external tests a little more complicated that internal tests such as the `Md5ChecksumTest` which has all of its logic built into this package. -When contributing an external test, following these steps may be helpful: +When contributing an internal test be sure to do the following: 1. Follow the steps above to set up `py-dcqc` and create your contribution. -2. Follow the instructions in the [README.md](https://github.com/Sage-Bionetworks-Workflows/nf-dcqc/blob/dev/README.md) +1. Include the following class attributes: + + - `tier`: An `int` value describing the complexity of the test contributed. `tier` values include: + - `1`: File Integrity + - `2`: Internal Conformance + - `3`: External Conformance + - `4`: Subjective Conformance + - `pass_code`: The exit code that will be returned by the command indicating a passed test. + - `fail_code`: The exit code that will be returned by the command indicating a failed test. + - `failure_reason_location`: The file (either `"std_out"` or `"std_err"`) that will contain the reason for a failed test. + - `target`: The target class that the test will be applied to. This value will be `SingleTarget` for individual files and `PairedTarget` for paired files. + +### Testing Your Changes + +1. Follow the instructions in the [README.md](https://github.com/Sage-Bionetworks-Workflows/nf-dcqc/blob/dev/README.md) file in the `nf-dcqc` respository to set up the workflow on your local machine. + - Run `git checkout dev` to switch to the developer branch -3. Build your local version of `py-dcqc` with your new changes with: +1. Build your local version of `py-dcqc` with your new changes with: + ```console src/docker/build.sh ``` + NOTE: This step assumes that you have docker installed and that it is running, and that you have `pipx` installed. -4. Follow `nf-dcqc` instructions to create a `nextflow run` command that tests your contribution. +1. Follow `nf-dcqc` instructions to create a `nextflow run` command that tests your contribution. + - You should include at least two files in your `nf-dcqc` input file ([example](https://github.com/Sage-Bionetworks-Workflows/nf-dcqc/blob/dev/testdata/input_full.csv)), one that you expect to pass your contributed test, and one that you expect to fail. - Include the `local` profile so that the workflow leverages your locally built `py-orca` container Example command (executed from within your local `nf-dcqc` repo clone): + ``` nextflow run main.nf -profile local,docker --input path/to/your/input.csv -- outdir output --required_tests ``` -5. Examine the final `suites.json` that is exported by the Nextflow workflow, if your contributed test bahaved as +1. Examine the final `output.csv` and `suites.json` files exported by the Nextflow workflow, if your contributed test bahaved as expected, you're done! If not, debug and make changes to your contribution and re-run the workflow. ### Troubleshooting @@ -291,7 +329,8 @@ on [PyPI], the following steps can be used to release a new version for 6. Run `tox -e publish -- --repository pypi` and check that everything was uploaded to [PyPI] correctly. -[^contrib1]: Even though, these resources focus on open source projects and +[^contrib1]: + Even though, these resources focus on open source projects and communities, the general ideas behind collaborating with other developers to collectively create software are general and can be applied to all sorts of environments, including private companies and proprietary code bases. From 96638c30f56b2f2d53bb5ec8c747b9c737df128c Mon Sep 17 00:00:00 2001 From: bwmac Date: Thu, 9 May 2024 10:30:09 -0600 Subject: [PATCH 22/30] adds error note --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a8cb560..971043d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -225,6 +225,8 @@ When contributing an internal test be sure to do the following: - `failure_reason_location`: The file (either `"std_out"` or `"std_err"`) that will contain the reason for a failed test. - `target`: The target class that the test will be applied to. This value will be `SingleTarget` for individual files and `PairedTarget` for paired files. +1. If possible, contribute an external test that returns different codes when it fails and when it errors out. Currently, a limitation of DCQC is that several external tests return the same `exit_code` when they fail and encounter an error. This will be addressed in future work that will add finer grained result interpretation. + ### Testing Your Changes 1. Follow the instructions in the [README.md](https://github.com/Sage-Bionetworks-Workflows/nf-dcqc/blob/dev/README.md) From 45d110649a6a1210631d112e0dfb017412e3a491 Mon Sep 17 00:00:00 2001 From: bwmac Date: Thu, 9 May 2024 10:32:39 -0600 Subject: [PATCH 23/30] adds DPE as codeowners --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..8b05a9a --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @Sage-Bionetworks-Workflows/dpe From cacaea73fc7d57b369f070280e06b8fbb6092dfd Mon Sep 17 00:00:00 2001 From: bwmac Date: Thu, 9 May 2024 11:20:12 -0600 Subject: [PATCH 24/30] Adds docstrings --- CONTRIBUTING.md | 4 ++++ src/dcqc/suites/suite_abc.py | 6 +++-- src/dcqc/suites/suites.py | 22 +++++++++++++++++++ src/dcqc/target.py | 2 +- src/dcqc/tests/base_test.py | 10 +++++++-- src/dcqc/tests/bioformats_info_test.py | 2 ++ src/dcqc/tests/file_extension_test.py | 2 ++ src/dcqc/tests/grep_date_test.py | 4 ++++ src/dcqc/tests/json_load_test.py | 2 ++ src/dcqc/tests/jsonld_load_test.py | 2 ++ src/dcqc/tests/libtiff_info_test.py | 2 ++ src/dcqc/tests/md5_checksum_test.py | 2 ++ src/dcqc/tests/ome_xml_schema_test.py | 2 ++ src/dcqc/tests/paired_fastq_parity_test.py | 2 ++ src/dcqc/tests/tiff_date_time_test.py | 4 ++++ src/dcqc/tests/tiff_tag_306_date_time_test.py | 4 ++++ src/dcqc/updaters.py | 6 +++-- 17 files changed, 71 insertions(+), 7 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 971043d..1dd104c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -194,6 +194,8 @@ When contributing an internal test be sure to do the following: 1. Follow the steps above to set up `py-dcqc` and create your contribution. +1. Include a class docstring that describes the purpose of the test. + 1. Include the following class attributes: - `tier`: An `int` value describing the complexity of the test contributed. `tier` values include: @@ -213,6 +215,8 @@ When contributing an internal test be sure to do the following: 1. Follow the steps above to set up `py-dcqc` and create your contribution. +1. Include a class docstring that describes the purpose of the test. + 1. Include the following class attributes: - `tier`: An `int` value describing the complexity of the test contributed. `tier` values include: diff --git a/src/dcqc/suites/suite_abc.py b/src/dcqc/suites/suite_abc.py index b19af13..d1760e9 100644 --- a/src/dcqc/suites/suite_abc.py +++ b/src/dcqc/suites/suite_abc.py @@ -15,6 +15,8 @@ class SuiteStatus(Enum): + """Status of a suite.""" + NONE = "NONE" # status not yet evaluated GREEN = "GREEN" # all tests passed RED = "RED" # one or more required tests failed @@ -207,7 +209,7 @@ def get_subclass_by_file_type( return registry[name] @property - def tests_by_name(self): + def tests_by_name(self) -> dict[str, BaseTest]: return {test.type: test for test in self.tests} def compute_tests(self) -> None: @@ -291,7 +293,7 @@ def from_dict(cls, dictionary: SerializedObject) -> SuiteABC: return suite @classmethod - def get_base_class(cls): + def get_base_class(cls) -> type[SuiteABC]: """Retrieve base class.""" return SuiteABC diff --git a/src/dcqc/suites/suites.py b/src/dcqc/suites/suites.py index 6e73e1b..0339fbe 100644 --- a/src/dcqc/suites/suites.py +++ b/src/dcqc/suites/suites.py @@ -4,21 +4,29 @@ class FileSuite(SuiteABC): + """Base class for all file-based test suites.""" + file_type = FileType.get_file_type("*") add_tests = (tests.FileExtensionTest, tests.Md5ChecksumTest) class JsonSuite(FileSuite): + """Suite class for JSON files.""" + file_type = FileType.get_file_type("JSON") add_tests = (tests.JsonLoadTest,) class JsonLdSuite(JsonSuite): + """Suite class for JSON-LD files.""" + file_type = FileType.get_file_type("JSON-LD") add_tests = (tests.JsonLdLoadTest,) class TiffSuite(FileSuite): + """Suite class for TIFF files.""" + file_type = FileType.get_file_type("TIFF") add_tests = ( tests.LibTiffInfoTest, @@ -28,30 +36,44 @@ class TiffSuite(FileSuite): class OmeTiffSuite(TiffSuite): + """Suite class for OME-TIFF files.""" + file_type = FileType.get_file_type("OME-TIFF") add_tests = (tests.OmeXmlSchemaTest, tests.BioFormatsInfoTest) class TSVSuite(FileSuite): + """Suite class for TSV files.""" + file_type = FileType.get_file_type("TSV") class BAMSuite(FileSuite): + """Suite class for BAM files.""" + file_type = FileType.get_file_type("BAM") class FastqSuite(FileSuite): + """Suite class for FASTQ files.""" + file_type = FileType.get_file_type("FASTQ") add_tests = (tests.PairedFastqParityTest,) class TXTSuite(FileSuite): + """Suite class for TXT files.""" + file_type = FileType.get_file_type("TXT") class CSVSuite(FileSuite): + """Suite class for CSV files.""" + file_type = FileType.get_file_type("CSV") class HDF5Suite(FileSuite): + """Suite class for HDF5 files.""" + file_type = FileType.get_file_type("HDF5") diff --git a/src/dcqc/target.py b/src/dcqc/target.py index 64ae1b7..5921142 100644 --- a/src/dcqc/target.py +++ b/src/dcqc/target.py @@ -86,7 +86,7 @@ def from_dict(cls, dictionary: SerializedObject) -> BaseTarget: return target @classmethod - def get_base_class(cls): + def get_base_class(cls) -> type[BaseTarget]: """Retrieve base class.""" return BaseTarget diff --git a/src/dcqc/tests/base_test.py b/src/dcqc/tests/base_test.py index 40d41ea..1e6e85e 100644 --- a/src/dcqc/tests/base_test.py +++ b/src/dcqc/tests/base_test.py @@ -18,6 +18,8 @@ class TestStatus(Enum): + """Enum for test statuses.""" + NONE = "pending" FAIL = "failed" PASS = "passed" @@ -55,7 +57,7 @@ def __init__(self, target: Target, skip: bool = False): self.target = target self._status = TestStatus.SKIP if skip else TestStatus.NONE - def skip(self): + def skip(self) -> None: """Force the test to be skipped.""" self._status = TestStatus.SKIP @@ -118,13 +120,15 @@ def import_module(self, name: str) -> ModuleType: return module @classmethod - def get_base_class(cls): + def get_base_class(cls) -> type[BaseTest]: """Retrieve base class.""" return BaseTest @dataclass class Process(SerializableMixin): + """Class for composing external processes""" + container: str command_args: InitVar[Sequence[str]] cpus: int = 1 @@ -159,6 +163,8 @@ def from_dict(cls, dictionary: SerializedObject) -> Process: class ExternalTestMixin(BaseTest): + """Class Mixin for external tests.""" + # Class attributes is_external_test = True diff --git a/src/dcqc/tests/bioformats_info_test.py b/src/dcqc/tests/bioformats_info_test.py index 7099efa..01b2596 100644 --- a/src/dcqc/tests/bioformats_info_test.py +++ b/src/dcqc/tests/bioformats_info_test.py @@ -3,6 +3,8 @@ class BioFormatsInfoTest(ExternalBaseTest): + """Tests if a file is valid OME-TIFF.""" + tier = 2 pass_code = 0 fail_code = 1 diff --git a/src/dcqc/tests/file_extension_test.py b/src/dcqc/tests/file_extension_test.py index a9e87c9..4aa4b35 100644 --- a/src/dcqc/tests/file_extension_test.py +++ b/src/dcqc/tests/file_extension_test.py @@ -3,6 +3,8 @@ class FileExtensionTest(InternalBaseTest): + """Tests if a file has a valid extension for its file type.""" + tier = 1 target: SingleTarget diff --git a/src/dcqc/tests/grep_date_test.py b/src/dcqc/tests/grep_date_test.py index 13ef2da..bb87b09 100644 --- a/src/dcqc/tests/grep_date_test.py +++ b/src/dcqc/tests/grep_date_test.py @@ -3,6 +3,10 @@ class GrepDateTest(ExternalBaseTest): + """Tests if a file has the word "date" or "time" in it. + Used for dtecting potential PHI in files. + """ + tier = 4 pass_code = 1 fail_code = 0 diff --git a/src/dcqc/tests/json_load_test.py b/src/dcqc/tests/json_load_test.py index ddb49b7..4ef2786 100644 --- a/src/dcqc/tests/json_load_test.py +++ b/src/dcqc/tests/json_load_test.py @@ -6,6 +6,8 @@ class JsonLoadTest(InternalBaseTest): + """Tests if a file can be loaded as JSON.""" + tier = 2 target: SingleTarget diff --git a/src/dcqc/tests/jsonld_load_test.py b/src/dcqc/tests/jsonld_load_test.py index 6a6877e..68dadca 100644 --- a/src/dcqc/tests/jsonld_load_test.py +++ b/src/dcqc/tests/jsonld_load_test.py @@ -5,6 +5,8 @@ class JsonLdLoadTest(InternalBaseTest): + """Tests if a file can be loaded as JSON-LD.""" + tier = 2 target: SingleTarget diff --git a/src/dcqc/tests/libtiff_info_test.py b/src/dcqc/tests/libtiff_info_test.py index 4c9c782..0dbdc7c 100644 --- a/src/dcqc/tests/libtiff_info_test.py +++ b/src/dcqc/tests/libtiff_info_test.py @@ -3,6 +3,8 @@ class LibTiffInfoTest(ExternalBaseTest): + """Tests if a file is valid TIFF.""" + tier = 2 pass_code = 0 fail_code = 1 diff --git a/src/dcqc/tests/md5_checksum_test.py b/src/dcqc/tests/md5_checksum_test.py index 35a0e43..0822e11 100644 --- a/src/dcqc/tests/md5_checksum_test.py +++ b/src/dcqc/tests/md5_checksum_test.py @@ -6,6 +6,8 @@ class Md5ChecksumTest(InternalBaseTest): + """Tests if a file has the expected MD5 checksum.""" + tier = 1 target: SingleTarget diff --git a/src/dcqc/tests/ome_xml_schema_test.py b/src/dcqc/tests/ome_xml_schema_test.py index 9df2a31..9b13f4a 100644 --- a/src/dcqc/tests/ome_xml_schema_test.py +++ b/src/dcqc/tests/ome_xml_schema_test.py @@ -3,6 +3,8 @@ class OmeXmlSchemaTest(ExternalBaseTest): + """Tests if OME-TIFF file has valid XML metadata.""" + tier = 2 pass_code = 0 fail_code = 1 diff --git a/src/dcqc/tests/paired_fastq_parity_test.py b/src/dcqc/tests/paired_fastq_parity_test.py index b8dec3b..8367b9e 100644 --- a/src/dcqc/tests/paired_fastq_parity_test.py +++ b/src/dcqc/tests/paired_fastq_parity_test.py @@ -7,6 +7,8 @@ class PairedFastqParityTest(InternalBaseTest): + """Test that paired FASTQ files have the same number of lines.""" + tier = 2 target: PairedTarget diff --git a/src/dcqc/tests/tiff_date_time_test.py b/src/dcqc/tests/tiff_date_time_test.py index 3cb077b..f888c2f 100644 --- a/src/dcqc/tests/tiff_date_time_test.py +++ b/src/dcqc/tests/tiff_date_time_test.py @@ -3,6 +3,10 @@ class TiffDateTimeTest(ExternalBaseTest): + """Tests if a TIFF file has the word "date" or "time" in its metadata. + Used for detecting potential PHI in files. + """ + tier = 4 pass_code = 1 fail_code = 0 diff --git a/src/dcqc/tests/tiff_tag_306_date_time_test.py b/src/dcqc/tests/tiff_tag_306_date_time_test.py index a290244..479e993 100644 --- a/src/dcqc/tests/tiff_tag_306_date_time_test.py +++ b/src/dcqc/tests/tiff_tag_306_date_time_test.py @@ -3,6 +3,10 @@ class TiffTag306DateTimeTest(ExternalBaseTest): + """Tests if a tiff file has the `306` date/time tag in its metadata. + Used for detecting potential PHI in files. + """ + tier = 4 pass_code = 1 fail_code = 0 diff --git a/src/dcqc/updaters.py b/src/dcqc/updaters.py index 70914e3..7a39071 100644 --- a/src/dcqc/updaters.py +++ b/src/dcqc/updaters.py @@ -10,6 +10,8 @@ @dataclass class CsvUpdater: + """Updates the CSV manifest file with DCQC results.""" + input_path: Path output_path: Path parser: CsvParser @@ -18,8 +20,8 @@ def __init__(self, input_path: Path, output_path: Path): self.output_path = output_path self.input_path = input_path - def update(self, suites: List[SuiteABC]): - suite_dict: dict[str, dict] = {} + def update(self, suites: List[SuiteABC]) -> None: + suite_dict: dict[str, dict[str, str]] = {} # TODO add support for suites with multiple files in them (multi) for suite in suites: url = suite.target.files[0].url From ba4d83fdff213ad5003e19ce25377c8823823f39 Mon Sep 17 00:00:00 2001 From: bwmac Date: Thu, 9 May 2024 15:25:27 -0600 Subject: [PATCH 25/30] only use one reason attribute --- CONTRIBUTING.md | 2 +- src/dcqc/tests/base_test.py | 13 +++---- src/dcqc/tests/file_extension_test.py | 2 +- src/dcqc/tests/json_load_test.py | 2 +- src/dcqc/tests/jsonld_load_test.py | 2 +- src/dcqc/tests/md5_checksum_test.py | 2 +- src/dcqc/tests/paired_fastq_parity_test.py | 4 +- tests/data/suite.json | 6 +-- tests/data/suites.json | 45 ++++++++-------------- tests/data/test.computed.json | 3 +- tests/data/test.external.json | 3 +- tests/data/test.internal.json | 3 +- tests/data/tests.json | 9 ++--- tests/test_internal_tests.py | 10 ++--- 14 files changed, 40 insertions(+), 66 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1dd104c..89cdd1a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -205,7 +205,7 @@ When contributing an internal test be sure to do the following: - `target`: The target class that the test will be applied to. This value will be `SingleTarget` for individual files and `PairedTarget` for paired files. 1. Implement the major logic of the test in the `compute_status` method. This should include a condition for returning a `status` of `TestStatus.PASS` when the test conditions are met and `TestStatus.FAIL` when they are not. - - For failing cases be sure to include a line setting the class' `failure_reason` to a helpful string that will tell users why the test failed before returning the `status`. + - For failing cases be sure to include a line setting the class' `status_reason` to a helpful string that will tell users why the test failed before returning the `status`. ### Contributing External Tests diff --git a/src/dcqc/tests/base_test.py b/src/dcqc/tests/base_test.py index 1e6e85e..f73e9a2 100644 --- a/src/dcqc/tests/base_test.py +++ b/src/dcqc/tests/base_test.py @@ -49,8 +49,7 @@ class BaseTest(SerializableMixin, SubclassRegistryMixin, ABC, Generic[Target]): # Instance attributes type: str target: Target - failure_reason: str = "" - error_reason: str = "" + status_reason: str = "" def __init__(self, target: Target, skip: bool = False): self.type = self.__class__.__name__ @@ -77,8 +76,7 @@ def to_dict(self) -> SerializedObject: "tier": self.tier, "is_external_test": self.is_external_test, "status": self._status.value, - "failure_reason": self.failure_reason, - "error_reason": self.error_reason, + "status_reason": self.status_reason, "target": self.target.to_dict(), } return test_dict @@ -103,8 +101,7 @@ def from_dict(cls, dictionary: SerializedObject) -> BaseTest: status = TestStatus(dictionary["status"]) test._status = status - test.failure_reason = dictionary["failure_reason"] - test.error_reason = dictionary["error_reason"] + test.status_reason = dictionary["status_reason"] return test @@ -217,10 +214,10 @@ def _interpret_process_outputs(self, outputs: dict[str, Path]) -> TestStatus: status = TestStatus.PASS elif exit_code == self.fail_code: status = TestStatus.FAIL - self.failure_reason = outputs[self.failure_reason_location].read_text() + self.status_reason = outputs[self.failure_reason_location].read_text() else: status = TestStatus.ERROR - self.error_reason = outputs["std_err"].read_text() + self.status_reason = outputs["std_err"].read_text() return status # TODO: Include process in serialized test dictionary diff --git a/src/dcqc/tests/file_extension_test.py b/src/dcqc/tests/file_extension_test.py index 4aa4b35..b1cd68c 100644 --- a/src/dcqc/tests/file_extension_test.py +++ b/src/dcqc/tests/file_extension_test.py @@ -15,7 +15,7 @@ def compute_status(self) -> TestStatus: file_extensions = file_type.file_extensions if not file.name.endswith(file_extensions): status = TestStatus.FAIL - self.failure_reason = ( + self.status_reason = ( f"File extension does not match one of: {file_extensions}" ) break diff --git a/src/dcqc/tests/json_load_test.py b/src/dcqc/tests/json_load_test.py index 4ef2786..ddc60db 100644 --- a/src/dcqc/tests/json_load_test.py +++ b/src/dcqc/tests/json_load_test.py @@ -17,7 +17,7 @@ def compute_status(self) -> TestStatus: status = TestStatus.PASS else: status = TestStatus.FAIL - self.failure_reason = "File content is unable to be loaded as JSON" + self.status_reason = "File content is unable to be loaded as JSON" return status def _can_be_loaded(self, path: Path) -> bool: diff --git a/src/dcqc/tests/jsonld_load_test.py b/src/dcqc/tests/jsonld_load_test.py index 68dadca..49e3c3c 100644 --- a/src/dcqc/tests/jsonld_load_test.py +++ b/src/dcqc/tests/jsonld_load_test.py @@ -16,7 +16,7 @@ def compute_status(self) -> TestStatus: status = TestStatus.PASS else: status = TestStatus.FAIL - self.failure_reason = "File content is unable to be loaded as JSON-LD" + self.status_reason = "File content is unable to be loaded as JSON-LD" return status def _can_be_loaded(self, path: Path) -> bool: diff --git a/src/dcqc/tests/md5_checksum_test.py b/src/dcqc/tests/md5_checksum_test.py index 0822e11..760d094 100644 --- a/src/dcqc/tests/md5_checksum_test.py +++ b/src/dcqc/tests/md5_checksum_test.py @@ -19,7 +19,7 @@ def compute_status(self) -> TestStatus: status = TestStatus.PASS else: status = TestStatus.FAIL - self.failure_reason = "Computed MD5 checksum does not match provided value" + self.status_reason = "Computed MD5 checksum does not match provided value" return status def _compute_md5_checksum(self, path: Path) -> str: diff --git a/src/dcqc/tests/paired_fastq_parity_test.py b/src/dcqc/tests/paired_fastq_parity_test.py index 8367b9e..0d61bd2 100644 --- a/src/dcqc/tests/paired_fastq_parity_test.py +++ b/src/dcqc/tests/paired_fastq_parity_test.py @@ -20,7 +20,7 @@ def compute_status(self) -> TestStatus: try: count = self._count_fastq_lines(path) except Exception: - self.failure_reason = "Unable to count FASTQ lines" + self.status_reason = "Unable to count FASTQ lines" return TestStatus.FAIL counts.append(count) @@ -29,7 +29,7 @@ def compute_status(self) -> TestStatus: status = TestStatus.PASS else: status = TestStatus.FAIL - self.failure_reason = "FASTQ files do not have the same number of lines" + self.status_reason = "FASTQ files do not have the same number of lines" return status def _count_fastq_lines(self, path: Path) -> int: diff --git a/tests/data/suite.json b/tests/data/suite.json index 607e188..437134c 100644 --- a/tests/data/suite.json +++ b/tests/data/suite.json @@ -30,16 +30,14 @@ "tier": 1, "is_external_test": false, "status": "passed", - "failure_reason": "", - "error_reason": "" + "status_reason": "" }, { "type": "LibTiffInfoTest", "tier": 2, "is_external_test": true, "status": "skipped", - "failure_reason": "", - "error_reason": "" + "status_reason": "" } ] } diff --git a/tests/data/suites.json b/tests/data/suites.json index abc02d4..c922343 100644 --- a/tests/data/suites.json +++ b/tests/data/suites.json @@ -31,40 +31,35 @@ "tier": 1, "is_external_test": false, "status": "passed", - "failure_reason": "", - "error_reason": "" + "status_reason": "" }, { "type": "GrepDateTest", "tier": 4, "is_external_test": true, "status": "passed", - "failure_reason": "", - "error_reason": "" + "status_reason": "" }, { "type": "LibTiffInfoTest", "tier": 2, "is_external_test": true, "status": "passed", - "failure_reason": "", - "error_reason": "" + "status_reason": "" }, { "type": "Md5ChecksumTest", "tier": 1, "is_external_test": false, "status": "passed", - "failure_reason": "", - "error_reason": "" + "status_reason": "" }, { "type": "TiffTag306DateTimeTest", "tier": 4, "is_external_test": true, "status": "passed", - "failure_reason": "", - "error_reason": "" + "status_reason": "" } ] }, @@ -100,40 +95,35 @@ "tier": 1, "is_external_test": false, "status": "passed", - "failure_reason": "", - "error_reason": "" + "status_reason": "" }, { "type": "GrepDateTest", "tier": 4, "is_external_test": true, "status": "failed", - "failure_reason": "test failed", - "error_reason": "" + "status_reason": "test failed" }, { "type": "LibTiffInfoTest", "tier": 2, "is_external_test": true, "status": "failed", - "failure_reason": "test failed", - "error_reason": "" + "status_reason": "test failed" }, { "type": "Md5ChecksumTest", "tier": 1, "is_external_test": false, "status": "passed", - "failure_reason": "", - "error_reason": "" + "status_reason": "" }, { "type": "TiffTag306DateTimeTest", "tier": 4, "is_external_test": true, "status": "passed", - "failure_reason": "", - "error_reason": "" + "status_reason": "" } ] }, @@ -169,40 +159,35 @@ "tier": 1, "is_external_test": false, "status": "passed", - "failure_reason": "", - "error_reason": "" + "status_reason": "" }, { "type": "GrepDateTest", "tier": 4, "is_external_test": true, "status": "passed", - "failure_reason": "", - "error_reason": "" + "status_reason": "" }, { "type": "LibTiffInfoTest", "tier": 2, "is_external_test": true, "status": "passed", - "failure_reason": "", - "error_reason": "" + "status_reason": "" }, { "type": "Md5ChecksumTest", "tier": 1, "is_external_test": false, "status": "passed", - "failure_reason": "", - "error_reason": "" + "status_reason": "" }, { "type": "TiffTag306DateTimeTest", "tier": 4, "is_external_test": true, "status": "failed", - "failure_reason": "test failed", - "error_reason": "" + "status_reason": "test failed" } ] } diff --git a/tests/data/test.computed.json b/tests/data/test.computed.json index b3dbb6a..c86f044 100644 --- a/tests/data/test.computed.json +++ b/tests/data/test.computed.json @@ -3,8 +3,7 @@ "tier": 1, "is_external_test": false, "status": "passed", - "failure_reason": "", - "error_reason": "", + "status_reason": "", "target": { "id": "001", "files": [ diff --git a/tests/data/test.external.json b/tests/data/test.external.json index 32f8911..f4cd893 100644 --- a/tests/data/test.external.json +++ b/tests/data/test.external.json @@ -3,8 +3,7 @@ "tier": 2, "is_external_test": true, "status": "pending", - "failure_reason": "", - "error_reason": "", + "status_reason": "", "target": { "id": "001", "files": [ diff --git a/tests/data/test.internal.json b/tests/data/test.internal.json index 7b9bc8d..0c47c29 100644 --- a/tests/data/test.internal.json +++ b/tests/data/test.internal.json @@ -3,8 +3,7 @@ "tier": 1, "is_external_test": false, "status": "pending", - "failure_reason": "", - "error_reason": "", + "status_reason": "", "target": { "id": "001", "files": [ diff --git a/tests/data/tests.json b/tests/data/tests.json index 28bdcec..be36038 100644 --- a/tests/data/tests.json +++ b/tests/data/tests.json @@ -4,8 +4,7 @@ "tier": 1, "is_external_test": false, "status": "pending", - "failure_reason": "", - "error_reason": "", + "status_reason": "", "target": { "id": "001", "files": [ @@ -27,8 +26,7 @@ "tier": 2, "is_external_test": true, "status": "pending", - "failure_reason": "", - "error_reason": "", + "status_reason": "", "target": { "id": "001", "files": [ @@ -50,8 +48,7 @@ "tier": 1, "is_external_test": false, "status": "passed", - "failure_reason": "", - "error_reason": "", + "status_reason": "", "target": { "id": "001", "files": [ diff --git a/tests/test_internal_tests.py b/tests/test_internal_tests.py index 3253616..7318d7a 100644 --- a/tests/test_internal_tests.py +++ b/tests/test_internal_tests.py @@ -52,7 +52,7 @@ def test_that_a_tiff_file_with_good_extensions_is_passed(self): def test_that_the_file_extension_test_works_on_incorrect_files(self): assert self.bad_txt_test.get_status() == TestStatus.FAIL - assert self.bad_txt_test.failure_reason == ( + assert self.bad_txt_test.status_reason == ( "File extension does not match one of: " f"{self.bad_txt_target.get_file_type().file_extensions}" ) @@ -72,7 +72,7 @@ def test_that_the_md5_checksum_test_works_on_a_correct_file(self): def test_that_the_md5_checksum_test_works_on_incorrect_files(self): assert self.bad_txt_test.get_status() == TestStatus.FAIL assert ( - self.bad_txt_test.failure_reason + self.bad_txt_test.status_reason == "Computed MD5 checksum does not match provided value" ) @@ -91,7 +91,7 @@ def test_that_the_json_load_test_works_on_a_correct_file(self): def test_that_the_json_load_test_works_on_incorrect_files(self): assert self.good_txt_test.get_status() == TestStatus.FAIL assert ( - self.good_txt_test.failure_reason + self.good_txt_test.status_reason == "File content is unable to be loaded as JSON" ) @@ -110,7 +110,7 @@ def test_that_the_jsonld_load_test_works_on_a_correct_file(self): def test_that_the_jsonld_load_test_works_on_incorrect_files(self): assert self.good_txt_test.get_status() == TestStatus.FAIL assert ( - self.good_txt_test.failure_reason + self.good_txt_test.status_reason == "File content is unable to be loaded as JSON-LD" ) @@ -149,6 +149,6 @@ def test_that_paired_fastq_parity_test_correctly_fails_different_fastq_files( ): assert self.bad_paired_test.get_status() == TestStatus.FAIL assert ( - self.bad_paired_test.failure_reason + self.bad_paired_test.status_reason == "FASTQ files do not have the same number of lines" ) From ab39fcf8784c0692b63ab918e499cfd7d54a1f75 Mon Sep 17 00:00:00 2001 From: bwmac Date: Thu, 9 May 2024 16:45:27 -0600 Subject: [PATCH 26/30] add tier enum --- CONTRIBUTING.md | 19 ++++++++++--------- src/dcqc/main.py | 2 +- src/dcqc/suites/suite_abc.py | 2 +- src/dcqc/tests/__init__.py | 8 +++++++- src/dcqc/tests/base_test.py | 13 +++++++++++-- src/dcqc/tests/bioformats_info_test.py | 4 ++-- src/dcqc/tests/file_extension_test.py | 4 ++-- src/dcqc/tests/grep_date_test.py | 4 ++-- src/dcqc/tests/json_load_test.py | 4 ++-- src/dcqc/tests/jsonld_load_test.py | 4 ++-- src/dcqc/tests/libtiff_info_test.py | 4 ++-- src/dcqc/tests/md5_checksum_test.py | 4 ++-- src/dcqc/tests/ome_xml_schema_test.py | 4 ++-- src/dcqc/tests/paired_fastq_parity_test.py | 4 ++-- src/dcqc/tests/tiff_date_time_test.py | 4 ++-- src/dcqc/tests/tiff_tag_306_date_time_test.py | 7 ++++--- tests/test_suites.py | 2 +- 17 files changed, 55 insertions(+), 38 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 89cdd1a..04555af 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -198,10 +198,11 @@ When contributing an internal test be sure to do the following: 1. Include the following class attributes: - - `tier`: An `int` value describing the complexity of the test contributed. `tier` values include: - - `1`: File Integrity - - `2`: Internal Conformance - - `3`: External Conformance + - `tier`: A `TestTier` enum describing the complexity of the test contributed. Valid `tier` values include: + - `FILE_INTEGRITY` + - `INTERNAL_CONFORMANCE` + - `EXTERNAL_CONFORMANCE` + - `SUBJECTIVE_CONFORMANCE` - `target`: The target class that the test will be applied to. This value will be `SingleTarget` for individual files and `PairedTarget` for paired files. 1. Implement the major logic of the test in the `compute_status` method. This should include a condition for returning a `status` of `TestStatus.PASS` when the test conditions are met and `TestStatus.FAIL` when they are not. @@ -219,11 +220,11 @@ When contributing an internal test be sure to do the following: 1. Include the following class attributes: - - `tier`: An `int` value describing the complexity of the test contributed. `tier` values include: - - `1`: File Integrity - - `2`: Internal Conformance - - `3`: External Conformance - - `4`: Subjective Conformance + - `tier`: A `TestTier` enum describing the complexity of the test contributed. Valid `tier` values include: + - `FILE_INTEGRITY` + - `INTERNAL_CONFORMANCE` + - `EXTERNAL_CONFORMANCE` + - `SUBJECTIVE_CONFORMANCE` - `pass_code`: The exit code that will be returned by the command indicating a passed test. - `fail_code`: The exit code that will be returned by the command indicating a failed test. - `failure_reason_location`: The file (either `"std_out"` or `"std_err"`) that will contain the reason for a failed test. diff --git a/src/dcqc/main.py b/src/dcqc/main.py index 72583a8..0065825 100644 --- a/src/dcqc/main.py +++ b/src/dcqc/main.py @@ -166,7 +166,7 @@ def list_tests(): "file_type": file_type_name, "edam_iri": file_type.edam_iri, "test_name": test_cls.__name__, - "test_tier": test_cls.tier, + "test_tier": test_cls.tier.value, "test_type": "external" if test_cls.is_external_test else "internal", } rows.append(test_dict) diff --git a/src/dcqc/suites/suite_abc.py b/src/dcqc/suites/suite_abc.py index d1760e9..80e0bf0 100644 --- a/src/dcqc/suites/suite_abc.py +++ b/src/dcqc/suites/suite_abc.py @@ -174,7 +174,7 @@ def list_test_classes_by_file_type(cls) -> dict[str, list[Type[BaseTest]]]: @classmethod def _default_required_tests(cls) -> list[str]: test_classes = cls.list_test_classes() - required_tests = filter(lambda test: test.tier <= 2, test_classes) + required_tests = filter(lambda test: test.tier.value <= 2, test_classes) required_test_names = [test.__name__ for test in required_tests] return required_test_names diff --git a/src/dcqc/tests/__init__.py b/src/dcqc/tests/__init__.py index cc37ba0..f775fd2 100644 --- a/src/dcqc/tests/__init__.py +++ b/src/dcqc/tests/__init__.py @@ -1,4 +1,10 @@ -from dcqc.tests.base_test import BaseTest, ExternalTestMixin, Process, TestStatus +from dcqc.tests.base_test import ( + BaseTest, + ExternalTestMixin, + Process, + TestStatus, + TestTier, +) from dcqc.tests.bioformats_info_test import BioFormatsInfoTest from dcqc.tests.file_extension_test import FileExtensionTest from dcqc.tests.grep_date_test import GrepDateTest diff --git a/src/dcqc/tests/base_test.py b/src/dcqc/tests/base_test.py index f73e9a2..53809a4 100644 --- a/src/dcqc/tests/base_test.py +++ b/src/dcqc/tests/base_test.py @@ -27,6 +27,15 @@ class TestStatus(Enum): ERROR = "error" +class TestTier(Enum): + """Enum for test tiers.""" + + FILE_INTEGRITY = 1 + INTERNAL_CONFORMANCE = 2 + EXTERNAL_CONFORMANCE = 3 + SUBJECTIVE_CONFORMANCE = 4 + + # TODO: Look into the @typing.final decorator class BaseTest(SerializableMixin, SubclassRegistryMixin, ABC, Generic[Target]): """Abstract base class for QC tests. @@ -43,7 +52,7 @@ class BaseTest(SerializableMixin, SubclassRegistryMixin, ABC, Generic[Target]): """ # Class attributes - tier: int + tier: TestTier is_external_test: bool = False # Instance attributes @@ -73,7 +82,7 @@ def compute_status(self) -> TestStatus: def to_dict(self) -> SerializedObject: test_dict = { "type": self.type, - "tier": self.tier, + "tier": self.tier.value, "is_external_test": self.is_external_test, "status": self._status.value, "status_reason": self.status_reason, diff --git a/src/dcqc/tests/bioformats_info_test.py b/src/dcqc/tests/bioformats_info_test.py index 01b2596..0b6aa1d 100644 --- a/src/dcqc/tests/bioformats_info_test.py +++ b/src/dcqc/tests/bioformats_info_test.py @@ -1,11 +1,11 @@ from dcqc.target import SingleTarget -from dcqc.tests.base_test import ExternalBaseTest, Process +from dcqc.tests.base_test import ExternalBaseTest, Process, TestTier class BioFormatsInfoTest(ExternalBaseTest): """Tests if a file is valid OME-TIFF.""" - tier = 2 + tier = TestTier.INTERNAL_CONFORMANCE pass_code = 0 fail_code = 1 failure_reason_location = "std_err" diff --git a/src/dcqc/tests/file_extension_test.py b/src/dcqc/tests/file_extension_test.py index b1cd68c..115521e 100644 --- a/src/dcqc/tests/file_extension_test.py +++ b/src/dcqc/tests/file_extension_test.py @@ -1,11 +1,11 @@ from dcqc.target import SingleTarget -from dcqc.tests.base_test import InternalBaseTest, TestStatus +from dcqc.tests.base_test import InternalBaseTest, TestStatus, TestTier class FileExtensionTest(InternalBaseTest): """Tests if a file has a valid extension for its file type.""" - tier = 1 + tier = TestTier.FILE_INTEGRITY target: SingleTarget def compute_status(self) -> TestStatus: diff --git a/src/dcqc/tests/grep_date_test.py b/src/dcqc/tests/grep_date_test.py index bb87b09..1f54692 100644 --- a/src/dcqc/tests/grep_date_test.py +++ b/src/dcqc/tests/grep_date_test.py @@ -1,5 +1,5 @@ from dcqc.target import SingleTarget -from dcqc.tests.base_test import ExternalBaseTest, Process +from dcqc.tests.base_test import ExternalBaseTest, Process, TestTier class GrepDateTest(ExternalBaseTest): @@ -7,7 +7,7 @@ class GrepDateTest(ExternalBaseTest): Used for dtecting potential PHI in files. """ - tier = 4 + tier = TestTier.SUBJECTIVE_CONFORMANCE pass_code = 1 fail_code = 0 failure_reason_location = "std_out" diff --git a/src/dcqc/tests/json_load_test.py b/src/dcqc/tests/json_load_test.py index ddc60db..edcdcc5 100644 --- a/src/dcqc/tests/json_load_test.py +++ b/src/dcqc/tests/json_load_test.py @@ -2,13 +2,13 @@ from pathlib import Path from dcqc.target import SingleTarget -from dcqc.tests.base_test import InternalBaseTest, TestStatus +from dcqc.tests.base_test import InternalBaseTest, TestStatus, TestTier class JsonLoadTest(InternalBaseTest): """Tests if a file can be loaded as JSON.""" - tier = 2 + tier = TestTier.INTERNAL_CONFORMANCE target: SingleTarget def compute_status(self) -> TestStatus: diff --git a/src/dcqc/tests/jsonld_load_test.py b/src/dcqc/tests/jsonld_load_test.py index 49e3c3c..08b1b3c 100644 --- a/src/dcqc/tests/jsonld_load_test.py +++ b/src/dcqc/tests/jsonld_load_test.py @@ -1,13 +1,13 @@ from pathlib import Path from dcqc.target import SingleTarget -from dcqc.tests.base_test import InternalBaseTest, TestStatus +from dcqc.tests.base_test import InternalBaseTest, TestStatus, TestTier class JsonLdLoadTest(InternalBaseTest): """Tests if a file can be loaded as JSON-LD.""" - tier = 2 + tier = TestTier.INTERNAL_CONFORMANCE target: SingleTarget def compute_status(self) -> TestStatus: diff --git a/src/dcqc/tests/libtiff_info_test.py b/src/dcqc/tests/libtiff_info_test.py index 0dbdc7c..356231b 100644 --- a/src/dcqc/tests/libtiff_info_test.py +++ b/src/dcqc/tests/libtiff_info_test.py @@ -1,11 +1,11 @@ from dcqc.target import SingleTarget -from dcqc.tests.base_test import ExternalBaseTest, Process +from dcqc.tests.base_test import ExternalBaseTest, Process, TestTier class LibTiffInfoTest(ExternalBaseTest): """Tests if a file is valid TIFF.""" - tier = 2 + tier = TestTier.INTERNAL_CONFORMANCE pass_code = 0 fail_code = 1 failure_reason_location = "std_err" diff --git a/src/dcqc/tests/md5_checksum_test.py b/src/dcqc/tests/md5_checksum_test.py index 760d094..e0e9661 100644 --- a/src/dcqc/tests/md5_checksum_test.py +++ b/src/dcqc/tests/md5_checksum_test.py @@ -2,13 +2,13 @@ from pathlib import Path from dcqc.target import SingleTarget -from dcqc.tests.base_test import InternalBaseTest, TestStatus +from dcqc.tests.base_test import InternalBaseTest, TestStatus, TestTier class Md5ChecksumTest(InternalBaseTest): """Tests if a file has the expected MD5 checksum.""" - tier = 1 + tier = TestTier.FILE_INTEGRITY target: SingleTarget def compute_status(self) -> TestStatus: diff --git a/src/dcqc/tests/ome_xml_schema_test.py b/src/dcqc/tests/ome_xml_schema_test.py index 9b13f4a..a5de40f 100644 --- a/src/dcqc/tests/ome_xml_schema_test.py +++ b/src/dcqc/tests/ome_xml_schema_test.py @@ -1,11 +1,11 @@ from dcqc.target import SingleTarget -from dcqc.tests.base_test import ExternalBaseTest, Process +from dcqc.tests.base_test import ExternalBaseTest, Process, TestTier class OmeXmlSchemaTest(ExternalBaseTest): """Tests if OME-TIFF file has valid XML metadata.""" - tier = 2 + tier = TestTier.INTERNAL_CONFORMANCE pass_code = 0 fail_code = 1 failure_reason_location = "std_out" diff --git a/src/dcqc/tests/paired_fastq_parity_test.py b/src/dcqc/tests/paired_fastq_parity_test.py index 0d61bd2..1451951 100644 --- a/src/dcqc/tests/paired_fastq_parity_test.py +++ b/src/dcqc/tests/paired_fastq_parity_test.py @@ -3,13 +3,13 @@ from typing import TextIO from dcqc.target import PairedTarget -from dcqc.tests.base_test import InternalBaseTest, TestStatus +from dcqc.tests.base_test import InternalBaseTest, TestStatus, TestTier class PairedFastqParityTest(InternalBaseTest): """Test that paired FASTQ files have the same number of lines.""" - tier = 2 + tier = TestTier.INTERNAL_CONFORMANCE target: PairedTarget def compute_status(self) -> TestStatus: diff --git a/src/dcqc/tests/tiff_date_time_test.py b/src/dcqc/tests/tiff_date_time_test.py index f888c2f..7ec71a8 100644 --- a/src/dcqc/tests/tiff_date_time_test.py +++ b/src/dcqc/tests/tiff_date_time_test.py @@ -1,5 +1,5 @@ from dcqc.target import SingleTarget -from dcqc.tests.base_test import ExternalBaseTest, Process +from dcqc.tests.base_test import ExternalBaseTest, Process, TestTier class TiffDateTimeTest(ExternalBaseTest): @@ -7,7 +7,7 @@ class TiffDateTimeTest(ExternalBaseTest): Used for detecting potential PHI in files. """ - tier = 4 + tier = TestTier.SUBJECTIVE_CONFORMANCE pass_code = 1 fail_code = 0 failure_reason_location = "std_out" diff --git a/src/dcqc/tests/tiff_tag_306_date_time_test.py b/src/dcqc/tests/tiff_tag_306_date_time_test.py index 479e993..cffc5c8 100644 --- a/src/dcqc/tests/tiff_tag_306_date_time_test.py +++ b/src/dcqc/tests/tiff_tag_306_date_time_test.py @@ -1,5 +1,5 @@ from dcqc.target import SingleTarget -from dcqc.tests.base_test import ExternalBaseTest, Process +from dcqc.tests.base_test import ExternalBaseTest, Process, TestTier class TiffTag306DateTimeTest(ExternalBaseTest): @@ -7,7 +7,7 @@ class TiffTag306DateTimeTest(ExternalBaseTest): Used for detecting potential PHI in files. """ - tier = 4 + tier = TestTier.SUBJECTIVE_CONFORMANCE pass_code = 1 fail_code = 0 failure_reason_location = "std_out" @@ -19,7 +19,8 @@ def generate_process(self) -> Process: command_args = [ "tifftools", "dump", - f"'{path.name}'", + "bad_file.file" + # f"'{path.name}'", "--json", "--silent", "|", diff --git a/tests/test_suites.py b/tests/test_suites.py index 2cf0348..ef6d5a0 100644 --- a/tests/test_suites.py +++ b/tests/test_suites.py @@ -79,7 +79,7 @@ def test_that_the_generic_file_suite_is_retrieved_for_an_unpaired_file_type(): def test_that_the_default_required_tests_are_only_tiers_1_and_2(test_suites): suite = test_suites["good_jsonld"] - assert all(test.tier <= 2 for test in suite.tests) + assert all(test.tier.value <= 2 for test in suite.tests) def test_that_skipped_tests_are_skipped_when_building_suite_from_tests(test_suites): From fd09758e1e91bdec003e843b35161f1527cf1bdd Mon Sep 17 00:00:00 2001 From: bwmac Date: Thu, 9 May 2024 16:56:27 -0600 Subject: [PATCH 27/30] revert intentional path error --- src/dcqc/tests/tiff_tag_306_date_time_test.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/dcqc/tests/tiff_tag_306_date_time_test.py b/src/dcqc/tests/tiff_tag_306_date_time_test.py index cffc5c8..f0c49fc 100644 --- a/src/dcqc/tests/tiff_tag_306_date_time_test.py +++ b/src/dcqc/tests/tiff_tag_306_date_time_test.py @@ -19,8 +19,7 @@ def generate_process(self) -> Process: command_args = [ "tifftools", "dump", - "bad_file.file" - # f"'{path.name}'", + f"'{path.name}'", "--json", "--silent", "|", From 48ba63902ea6ff881d167cd6d4d1953c451e88cf Mon Sep 17 00:00:00 2001 From: bwmac Date: Fri, 10 May 2024 09:19:03 -0600 Subject: [PATCH 28/30] pre-commit fixes --- src/dcqc/suites/suite_abc.py | 2 +- src/dcqc/target.py | 2 +- src/dcqc/tests/base_test.py | 2 +- src/dcqc/updaters.py | 5 +++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/dcqc/suites/suite_abc.py b/src/dcqc/suites/suite_abc.py index 80e0bf0..0954237 100644 --- a/src/dcqc/suites/suite_abc.py +++ b/src/dcqc/suites/suite_abc.py @@ -293,7 +293,7 @@ def from_dict(cls, dictionary: SerializedObject) -> SuiteABC: return suite @classmethod - def get_base_class(cls) -> type[SuiteABC]: + def get_base_class(cls): """Retrieve base class.""" return SuiteABC diff --git a/src/dcqc/target.py b/src/dcqc/target.py index 5921142..64ae1b7 100644 --- a/src/dcqc/target.py +++ b/src/dcqc/target.py @@ -86,7 +86,7 @@ def from_dict(cls, dictionary: SerializedObject) -> BaseTarget: return target @classmethod - def get_base_class(cls) -> type[BaseTarget]: + def get_base_class(cls): """Retrieve base class.""" return BaseTarget diff --git a/src/dcqc/tests/base_test.py b/src/dcqc/tests/base_test.py index 53809a4..5e789e8 100644 --- a/src/dcqc/tests/base_test.py +++ b/src/dcqc/tests/base_test.py @@ -126,7 +126,7 @@ def import_module(self, name: str) -> ModuleType: return module @classmethod - def get_base_class(cls) -> type[BaseTest]: + def get_base_class(cls): """Retrieve base class.""" return BaseTest diff --git a/src/dcqc/updaters.py b/src/dcqc/updaters.py index 7a39071..9c3926d 100644 --- a/src/dcqc/updaters.py +++ b/src/dcqc/updaters.py @@ -1,7 +1,7 @@ from csv import DictWriter from dataclasses import dataclass from pathlib import Path -from typing import List +from typing import Any, List from dcqc.parsers import CsvParser from dcqc.suites.suite_abc import SuiteABC @@ -21,7 +21,7 @@ def __init__(self, input_path: Path, output_path: Path): self.input_path = input_path def update(self, suites: List[SuiteABC]) -> None: - suite_dict: dict[str, dict[str, str]] = {} + suite_dict: dict[str, dict[str, Any]] = {} # TODO add support for suites with multiple files in them (multi) for suite in suites: url = suite.target.files[0].url @@ -37,6 +37,7 @@ def update(self, suites: List[SuiteABC]) -> None: suite_dict[url]["failed_tests"].append(test.type) if test._status == TestStatus.ERROR: suite_dict[url]["errored_tests"].append(test.type) + # Create CSV data structure row_list = [] parser = CsvParser(self.input_path) From d20ef1b9d0a8e589d840354693f0c8842b341348 Mon Sep 17 00:00:00 2001 From: bwmac Date: Fri, 10 May 2024 09:39:01 -0600 Subject: [PATCH 29/30] updates ci workflow name --- .github/workflows/ci.yml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e5cc84..e3baa55 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,20 +2,20 @@ # MODIFY IT ACCORDING TO YOUR NEEDS! # Reference: https://docs.github.com/en/actions -name: tests +name: test on: push: # Avoid using all the resources/limits available by checking only # relevant branches and tags. Other branches can be checked via PRs. branches: [main] - tags: ['v[0-9]*', '[0-9]+.[0-9]+*'] # Match tags that resemble a version - pull_request: # Run in every PR - workflow_dispatch: # Allow manually triggering the workflow + tags: ["v[0-9]*", "[0-9]+.[0-9]+*"] # Match tags that resemble a version + pull_request: # Run in every PR + workflow_dispatch: # Allow manually triggering the workflow schedule: # Run roughly every 15 days at 00:00 UTC # (useful to check if updates on dependencies break the package) - - cron: '0 0 1,16 * *' + - cron: "0 0 1,16 * *" concurrency: group: >- @@ -31,9 +31,9 @@ jobs: tarball-path: ${{ steps.distribution-paths.outputs.tarball }} steps: - uses: actions/checkout@v3 - with: {fetch-depth: 0} # deep clone for setuptools-scm + with: { fetch-depth: 0 } # deep clone for setuptools-scm - uses: actions/setup-python@v4 - with: {python-version: "3.11"} + with: { python-version: "3.11" } - name: Run static analysis and format checkers run: pipx run pre-commit run --all-files --show-diff-on-failure - name: Install tox-gh plugin @@ -60,11 +60,11 @@ jobs: strategy: matrix: python: - - "3.9" # oldest Python that is supported - - "3.11" # newest Python that is stable + - "3.9" # oldest Python that is supported + - "3.11" # newest Python that is stable platform: - - ubuntu-latest - - macos-latest + - ubuntu-latest + - macos-latest # TODO: Debug the Windows issues # - windows-latest env: @@ -77,7 +77,7 @@ jobs: with: python-version: ${{ matrix.python }} - uses: actions/download-artifact@v3 - with: {name: python-distribution-files, path: dist/} + with: { name: python-distribution-files, path: dist/ } - name: Install tox-gh plugin run: python -m pip install tox-gh>=1.2 - name: Setup test suite @@ -106,9 +106,9 @@ jobs: steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 - with: {python-version: "3.11"} + with: { python-version: "3.11" } - uses: actions/download-artifact@v3 - with: {name: python-distribution-files, path: dist/} + with: { name: python-distribution-files, path: dist/ } - name: Publish Python Package to PyPI env: TWINE_REPOSITORY: pypi @@ -123,7 +123,7 @@ jobs: steps: - uses: actions/checkout@v3 - uses: actions/download-artifact@v3 - with: {name: python-distribution-files, path: dist/} + with: { name: python-distribution-files, path: dist/ } - uses: docker/setup-qemu-action@v2 - uses: docker/setup-buildx-action@v2 - uses: docker/login-action@v2 From cfea9299cf892dfd13976fa852dfb1f7ed80da68 Mon Sep 17 00:00:00 2001 From: bwmac Date: Fri, 10 May 2024 09:49:12 -0600 Subject: [PATCH 30/30] adds keep-alive --- .github/workflows/ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e3baa55..977a0e3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,6 +54,10 @@ jobs: name: python-distribution-files path: dist/ retention-days: 1 + - name: Keepalive Workflow + uses: gautamkrishnar/keepalive-workflow@1.1.0 + with: + time_elapsed: 44 test: needs: prepare