From c7932483d0765918e35eb7f157e92be88c60efc7 Mon Sep 17 00:00:00 2001 From: Maximilien Cuony Date: Wed, 14 Jan 2026 15:45:42 +0100 Subject: [PATCH] [tooling] Use optional in ImplicitDicts --- .../systems/configuration.py | 8 +- .../systems/test/configuration.py | 4 +- monitoring/mock_uss/database.py | 13 ++- monitoring/mock_uss/flights/database.py | 4 +- monitoring/mock_uss/geoawareness/database.py | 6 +- monitoring/mock_uss/riddp/behavior.py | 6 +- monitoring/mock_uss/ridsp/behavior.py | 10 +-- monitoring/mock_uss/ridsp/database.py | 4 +- monitoring/mock_uss/tracer/log_types.py | 8 +- .../mock_uss/tracer/observation_areas.py | 22 ++--- monitoring/mock_uss/tracer/tracer_poll.py | 8 +- .../clients/flight_planning/flight_info.py | 32 ++++---- .../flight_planning/flight_info_template.py | 12 +-- .../clients/flight_planning/planning.py | 8 +- .../flight_planning/test_preparation.py | 8 +- .../clients/geospatial_info/querying.py | 14 ++-- .../mock_uss/mock_uss_scd_injection_api.py | 6 +- monitoring/monitorlib/fetch/__init__.py | 26 +++--- monitoring/monitorlib/fetch/rid.py | 36 ++++---- monitoring/monitorlib/fetch/scd.py | 8 +- monitoring/monitorlib/geo.py | 12 +-- monitoring/monitorlib/geotemporal.py | 22 ++--- monitoring/monitorlib/idempotency.py | 6 +- monitoring/monitorlib/mutate/rid.py | 10 +-- monitoring/monitorlib/mutate/scd.py | 4 +- .../rid_automated_testing/injection_api.py | 3 +- monitoring/monitorlib/subscription_params.py | 8 +- monitoring/monitorlib/temporal.py | 23 ++++-- monitoring/monitorlib/transformations.py | 16 ++-- .../documentation/definitions.py | 12 +-- .../flight_planning/planner_combinations.py | 4 +- .../configurations/configuration.py | 82 +++++++++---------- monitoring/uss_qualifier/main.py | 6 +- .../reports/capability_definitions.py | 14 ++-- monitoring/uss_qualifier/reports/report.py | 46 +++++------ .../reports/sequence_view/summary_types.py | 20 ++--- .../reports/tested_requirements/data_types.py | 10 +-- .../reports/validation/definitions.py | 54 ++++++------ .../uss_qualifier/requirements/definitions.py | 10 +-- .../resources/astm/f3548/v21/dss.py | 6 +- .../resources/communications/auth_adapter.py | 6 +- .../resources/dev/test_exclusions.py | 6 +- monitoring/uss_qualifier/resources/files.py | 4 +- .../flight_planning/flight_intent.py | 16 ++-- .../flight_planning/flight_planner.py | 8 +- .../flight_planning/flight_planners.py | 6 +- .../geospatial_info_providers.py | 6 +- .../interuss/geospatial_map/definitions.py | 6 +- .../geospatial_map/feature_check_table.py | 10 +-- .../resources/interuss/mock_uss/client.py | 4 +- .../resources/interuss/query_behavior.py | 12 +-- .../resources/interuss/uss_identification.py | 10 +-- .../resources/netrid/flight_data.py | 21 +++-- .../resources/netrid/flight_data_resources.py | 6 +- .../uss_qualifier/resources/planning_area.py | 4 +- .../resources/versioning/client.py | 4 +- .../scenarios/astm/utm/test_steps.py | 8 +- .../scenarios/documentation/definitions.py | 16 ++-- .../uss_qualifier/suites/definitions.py | 18 ++-- 59 files changed, 399 insertions(+), 383 deletions(-) diff --git a/monitoring/deployment_manager/systems/configuration.py b/monitoring/deployment_manager/systems/configuration.py index bd512166d4..d149630efb 100644 --- a/monitoring/deployment_manager/systems/configuration.py +++ b/monitoring/deployment_manager/systems/configuration.py @@ -1,4 +1,4 @@ -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.deployment_manager.systems.dss.configuration import DSS from monitoring.deployment_manager.systems.test.configuration import Test @@ -14,11 +14,11 @@ class KubernetesCluster(ImplicitDict): class DeploymentSpec(ImplicitDict): - cluster: KubernetesCluster | None + cluster: Optional[KubernetesCluster] """Definition of Kubernetes cluster containing this deployment.""" - test: Test | None + test: Optional[Test] """Test systems in this deployment.""" - dss: DSS | None + dss: Optional[DSS] """DSS instance in this deployment.""" diff --git a/monitoring/deployment_manager/systems/test/configuration.py b/monitoring/deployment_manager/systems/test/configuration.py index 09b861b134..3c2b90bf9a 100644 --- a/monitoring/deployment_manager/systems/test/configuration.py +++ b/monitoring/deployment_manager/systems/test/configuration.py @@ -1,4 +1,4 @@ -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional class TestV1(ImplicitDict): @@ -6,4 +6,4 @@ class TestV1(ImplicitDict): class Test(ImplicitDict): - v1: TestV1 | None + v1: Optional[TestV1] diff --git a/monitoring/mock_uss/database.py b/monitoring/mock_uss/database.py index 6df90b1eda..60945ed8eb 100644 --- a/monitoring/mock_uss/database.py +++ b/monitoring/mock_uss/database.py @@ -1,14 +1,19 @@ import json -from implicitdict import ImplicitDict, StringBasedDateTime, StringBasedTimeDelta +from implicitdict import ( + ImplicitDict, + Optional, + StringBasedDateTime, + StringBasedTimeDelta, +) from monitoring.monitorlib.errors import stacktrace_string from monitoring.monitorlib.multiprocessing import SynchronizedValue class PeriodicTaskStatus(ImplicitDict): - last_execution_time: StringBasedDateTime | None = None - period: StringBasedTimeDelta | None = None + last_execution_time: Optional[StringBasedDateTime] = None + period: Optional[StringBasedTimeDelta] = None executing: bool = False @@ -43,7 +48,7 @@ class Database(ImplicitDict): periodic_tasks: dict[str, PeriodicTaskStatus] """Tasks to perform periodically, by name""" - most_recent_periodic_check: StringBasedDateTime | None + most_recent_periodic_check: Optional[StringBasedDateTime] """Timestamp of most recent time periodic task loop iterated""" diff --git a/monitoring/mock_uss/flights/database.py b/monitoring/mock_uss/flights/database.py index f091958b48..97ca0ea1bb 100644 --- a/monitoring/mock_uss/flights/database.py +++ b/monitoring/mock_uss/flights/database.py @@ -1,7 +1,7 @@ import json from datetime import timedelta -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from uas_standards.astm.f3548.v21.api import OperationalIntent from monitoring.mock_uss.user_interactions.notifications import UserNotification @@ -19,7 +19,7 @@ class FlightRecord(ImplicitDict): flight_info: FlightInfo op_intent: OperationalIntent - mod_op_sharing_behavior: MockUssFlightBehavior | None = None + mod_op_sharing_behavior: Optional[MockUssFlightBehavior] = None locked: bool = False diff --git a/monitoring/mock_uss/geoawareness/database.py b/monitoring/mock_uss/geoawareness/database.py index 16c35cfd73..49e3b6d80b 100644 --- a/monitoring/mock_uss/geoawareness/database.py +++ b/monitoring/mock_uss/geoawareness/database.py @@ -1,6 +1,6 @@ import json -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from uas_standards.eurocae_ed269 import ED269Schema from uas_standards.interuss.automated_testing.geo_awareness.v1.api import ( CreateGeozoneSourceRequest, @@ -17,8 +17,8 @@ class ExistingRecordException(ValueError): class SourceRecord(ImplicitDict): definition: CreateGeozoneSourceRequest state: GeozoneSourceResponseResult - message: str | None - geozone_ed269: ED269Schema | None + message: Optional[str] + geozone_ed269: Optional[ED269Schema] class Database(ImplicitDict): diff --git a/monitoring/mock_uss/riddp/behavior.py b/monitoring/mock_uss/riddp/behavior.py index ab5821361a..691f93be60 100644 --- a/monitoring/mock_uss/riddp/behavior.py +++ b/monitoring/mock_uss/riddp/behavior.py @@ -1,8 +1,8 @@ -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional ServiceProviderID = str class DisplayProviderBehavior(ImplicitDict): - always_omit_recent_paths: bool | None = False - do_not_display_flights_from: list[ServiceProviderID] | None = [] + always_omit_recent_paths: Optional[bool] = False + do_not_display_flights_from: Optional[list[ServiceProviderID]] = [] diff --git a/monitoring/mock_uss/ridsp/behavior.py b/monitoring/mock_uss/ridsp/behavior.py index 0a16f93f3c..9239e0945e 100644 --- a/monitoring/mock_uss/ridsp/behavior.py +++ b/monitoring/mock_uss/ridsp/behavior.py @@ -1,4 +1,4 @@ -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from uas_standards.astm.f3411.v19.api import RIDFlight from monitoring.monitorlib.delay import sleep @@ -8,10 +8,10 @@ class ServiceProviderBehavior(ImplicitDict): - switch_latitude_and_longitude_when_reporting: bool | None = False - use_agl_instead_of_wgs84_for_altitude: bool | None = False - use_feet_instead_of_meters_for_altitude: bool | None = False - delay_flight_report_s: int | None = 0 + switch_latitude_and_longitude_when_reporting: Optional[bool] = False + use_agl_instead_of_wgs84_for_altitude: Optional[bool] = False + use_feet_instead_of_meters_for_altitude: Optional[bool] = False + delay_flight_report_s: Optional[int] = 0 def adjust_reported_flight( diff --git a/monitoring/mock_uss/ridsp/database.py b/monitoring/mock_uss/ridsp/database.py index 54497f1464..3732c8b291 100644 --- a/monitoring/mock_uss/ridsp/database.py +++ b/monitoring/mock_uss/ridsp/database.py @@ -1,6 +1,6 @@ import json -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.monitorlib.multiprocessing import SynchronizedValue from monitoring.monitorlib.rid_automated_testing import injection_api @@ -14,7 +14,7 @@ class TestRecord(ImplicitDict): version: str flights: list[injection_api.TestFlight] - isa_version: str | None = None + isa_version: Optional[str] = None def __init__(self, **kwargs): kwargs["flights"] = [ diff --git a/monitoring/mock_uss/tracer/log_types.py b/monitoring/mock_uss/tracer/log_types.py index f7a5ef33a4..14c8df41db 100644 --- a/monitoring/mock_uss/tracer/log_types.py +++ b/monitoring/mock_uss/tracer/log_types.py @@ -3,7 +3,7 @@ import sys from abc import abstractmethod -from implicitdict import ImplicitDict, StringBasedDateTime +from implicitdict import ImplicitDict, Optional, StringBasedDateTime from monitoring.monitorlib.fetch import RequestDescription, summarize from monitoring.monitorlib.fetch import rid as rid_fetch @@ -124,7 +124,7 @@ def prefix_code() -> str: existing_subscription: rid_fetch.FetchedSubscription """Subscription, as read from the DSS just before deletion.""" - deleted_subscription: rid_mutate.ChangedSubscription | None + deleted_subscription: Optional[rid_mutate.ChangedSubscription] """Subscription returned from DSS upon deletion.""" @@ -214,7 +214,7 @@ def prefix_code() -> str: existing_subscription: scd_fetch.FetchedSubscription """Subscription, as read from the DSS just before deletion.""" - deleted_subscription: scd_mutate.MutatedSubscription | None + deleted_subscription: Optional[scd_mutate.MutatedSubscription] """Subscription returned from DSS upon deletion.""" @@ -270,7 +270,7 @@ class ObservationAreaImportError(TracerLogEntry): def prefix_code() -> str: return "import_obs_areas_error" - rid_subscriptions: rid_fetch.FetchedSubscriptions | None + rid_subscriptions: Optional[rid_fetch.FetchedSubscriptions] """Result of attempting to fetch RID subscriptions""" diff --git a/monitoring/mock_uss/tracer/observation_areas.py b/monitoring/mock_uss/tracer/observation_areas.py index 217504fae2..794e94bda7 100644 --- a/monitoring/mock_uss/tracer/observation_areas.py +++ b/monitoring/mock_uss/tracer/observation_areas.py @@ -1,4 +1,4 @@ -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.monitorlib.geotemporal import Volume4D from monitoring.monitorlib.infrastructure import AuthSpec @@ -45,7 +45,7 @@ class F3548ObservationArea(ImplicitDict): poll: bool """This area observes by periodically polling for information.""" - subscription_id: str | None = None + subscription_id: Optional[str] = None """The F3548 subscription ID established to provide observation via notifications.""" @@ -58,10 +58,10 @@ class ObservationArea(ImplicitDict): area: Volume4D """Spatial-temporal area being observed.""" - f3411: F3411ObservationArea | None = None + f3411: Optional[F3411ObservationArea] = None """How F3411 information is being observed (or not observed, if not specified).""" - f3548: F3548ObservationArea | None = None + f3548: Optional[F3548ObservationArea] = None """How F3548 information is being observed (or not observed, if not specified).""" @property @@ -75,12 +75,12 @@ def polls(self) -> bool: class F3411ObservationAreaRequest(ImplicitDict): """How to observe F3411 activity.""" - auth_spec: AuthSpec | None = None + auth_spec: Optional[AuthSpec] = None """If specified, use this auth spec when performing observation activities. If not specified or blank, use auth spec provided on the command line.""" - dss_base_url: str | None = None + dss_base_url: Optional[str] = None """If specified, use the DSS at this base URL when performing relevant observation activities. If not specified or blank, use DSS URL provided on the command line.""" @@ -98,12 +98,12 @@ class F3411ObservationAreaRequest(ImplicitDict): class F3548ObservationAreaRequest(ImplicitDict): """How to observe F3548 activity.""" - auth_spec: AuthSpec | None = None + auth_spec: Optional[AuthSpec] = None """If specified, use this auth spec when performing observation activities. If not specified or blank, use auth spec provided on the command line.""" - dss_base_url: str | None = None + dss_base_url: Optional[str] = None """If specified, use the DSS at this base URL when performing relevant observation activities. If not specified or blank, use DSS URL provided on the command line.""" @@ -127,10 +127,10 @@ class ObservationAreaRequest(ImplicitDict): area: Volume4D """Spatial-temporal area that should be observed.""" - f3411: F3411ObservationAreaRequest | None = None + f3411: Optional[F3411ObservationAreaRequest] = None """How to observe F3411 (NetRID) activity.""" - f3548: F3548ObservationAreaRequest | None = None + f3548: Optional[F3548ObservationAreaRequest] = None """How to observe F3548 (strategic coordination, conformance monitoring, and constraints) activity.""" @property @@ -168,7 +168,7 @@ class ImportObservationAreasRequest(ImplicitDict): area: Volume4D """Spatial-temporal area containing subscriptions to be imported.""" - f3411: RIDVersion | None = None + f3411: Optional[RIDVersion] = None """If specified, search for subscriptions using this F3411 version.""" f3548: bool = False diff --git a/monitoring/mock_uss/tracer/tracer_poll.py b/monitoring/mock_uss/tracer/tracer_poll.py index 5b22c68eff..7914c66be1 100755 --- a/monitoring/mock_uss/tracer/tracer_poll.py +++ b/monitoring/mock_uss/tracer/tracer_poll.py @@ -3,7 +3,7 @@ import sys import arrow -from implicitdict import ImplicitDict, StringBasedDateTime +from implicitdict import ImplicitDict, Optional, StringBasedDateTime from monitoring.mock_uss.app import webapp from monitoring.mock_uss.tracer import context, diff, tracerlog @@ -55,9 +55,9 @@ class PollingStatus(ImplicitDict): class PollingValues(ImplicitDict): need_line_break: bool = False - last_isa_result: FetchedISAs | None = None - last_ops_result: FetchedEntities | None = None - last_constraints_result: FetchedEntities | None = None + last_isa_result: Optional[FetchedISAs] = None + last_ops_result: Optional[FetchedEntities] = None + last_constraints_result: Optional[FetchedEntities] = None polling_values = SynchronizedValue[PollingValues]( diff --git a/monitoring/monitorlib/clients/flight_planning/flight_info.py b/monitoring/monitorlib/clients/flight_planning/flight_info.py index a2ca876bbf..bf451c0516 100644 --- a/monitoring/monitorlib/clients/flight_planning/flight_info.py +++ b/monitoring/monitorlib/clients/flight_planning/flight_info.py @@ -2,7 +2,7 @@ from enum import Enum -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from uas_standards.ansi_cta_2063_a import SerialNumber from uas_standards.astm.f3548.v21 import api as f3548v21 from uas_standards.en4709_02 import OperatorRegistrationNumber @@ -21,7 +21,7 @@ class ASTMF354821OpIntentInformation(ImplicitDict): """Information provided about a flight plan that is necessary for ASTM F3548-21.""" - priority: Priority | None + priority: Optional[Priority] # ===== U-space ===== @@ -76,7 +76,7 @@ class FlightAuthorisationData(ImplicitDict): identification_technologies: list[str] """Technology used to identify the UAS. Required by ANNEX IV of COMMISSION IMPLEMENTING REGULATION (EU) 2021/664, paragraph 6.""" - uas_type_certificate: str | None + uas_type_certificate: Optional[str] """Provisional field. Not applicable as of September 2021. Required only if `uas_class` is set to `other` by ANNEX IV of COMMISSION IMPLEMENTING REGULATION (EU) 2021/664, paragraph 4.""" connectivity_methods: list[str] @@ -95,7 +95,7 @@ class FlightAuthorisationData(ImplicitDict): Required by ANNEX IV of COMMISSION IMPLEMENTING REGULATION (EU) 2021/664, paragraph 10. """ - uas_id: str | None + uas_id: Optional[str] """When applicable, the registration number of the unmanned aircraft. This is expressed using the nationality and registration mark of the unmanned aircraft in line with ICAO Annex 7. @@ -146,28 +146,28 @@ class RPAS26FlightDetailsFlightProfile(str, Enum): class RPAS26FlightDetails(ImplicitDict): """Information about a flight necessary to plan successfully using the RPAS Platform Operating Rules version 2.6.""" - operator_type: RPAS26FlightDetailsOperatorType | None + operator_type: Optional[RPAS26FlightDetailsOperatorType] """The type of operator.""" - uas_serial_numbers: list[str] | None + uas_serial_numbers: Optional[list[str]] """The list of UAS/drone serial numbers that will be operated during the operation.""" - uas_registration_numbers: list[str] | None + uas_registration_numbers: Optional[list[str]] """The list of UAS/drone registration numbers that will be operated during the operation.""" - aircraft_type: RPAS26FlightDetailsAircraftType | None + aircraft_type: Optional[RPAS26FlightDetailsAircraftType] """Type of vehicle being used as per ASTM F3411-22a.""" - flight_profile: RPAS26FlightDetailsFlightProfile | None + flight_profile: Optional[RPAS26FlightDetailsFlightProfile] """Type of flight profile.""" - pilot_license_number: str | None + pilot_license_number: Optional[str] """License number for the pilot.""" - pilot_phone_number: str | None + pilot_phone_number: Optional[str] """Contact phone number for the pilot.""" - operator_number: str | None + operator_number: Optional[str] """Operator number.""" @@ -255,13 +255,13 @@ class FlightInfo(ImplicitDict): basic_information: BasicFlightPlanInformation - astm_f3548_21: ASTMF354821OpIntentInformation | None + astm_f3548_21: Optional[ASTMF354821OpIntentInformation] - uspace_flight_authorisation: FlightAuthorisationData | None + uspace_flight_authorisation: Optional[FlightAuthorisationData] - rpas_operating_rules_2_6: RPAS26FlightDetails | None + rpas_operating_rules_2_6: Optional[RPAS26FlightDetails] - additional_information: dict | None + additional_information: Optional[dict] """Any information relevant to a particular jurisdiction or use case not described in the standard schema. The keys and values must be agreed upon between the test designers and USSs under test.""" @staticmethod diff --git a/monitoring/monitorlib/clients/flight_planning/flight_info_template.py b/monitoring/monitorlib/clients/flight_planning/flight_info_template.py index 63801262a7..51c8aa16e8 100644 --- a/monitoring/monitorlib/clients/flight_planning/flight_info_template.py +++ b/monitoring/monitorlib/clients/flight_planning/flight_info_template.py @@ -1,4 +1,4 @@ -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from uas_standards.interuss.automated_testing.scd.v1 import api as scd_api from monitoring.monitorlib.clients.flight_planning.flight_info import ( @@ -41,16 +41,16 @@ class FlightInfoTemplate(ImplicitDict): basic_information: BasicFlightPlanInformationTemplate - astm_f3548_21: ASTMF354821OpIntentInformation | None + astm_f3548_21: Optional[ASTMF354821OpIntentInformation] - uspace_flight_authorisation: FlightAuthorisationData | None + uspace_flight_authorisation: Optional[FlightAuthorisationData] - rpas_operating_rules_2_6: RPAS26FlightDetails | None + rpas_operating_rules_2_6: Optional[RPAS26FlightDetails] - additional_information: dict | None + additional_information: Optional[dict] """Any information relevant to a particular jurisdiction or use case not described in the standard schema. The keys and values must be agreed upon between the test designers and USSs under test.""" - transformations: list[Transformation] | None + transformations: Optional[list[Transformation]] """If specified, transform this flight according to these transformations in order (after all templates are resolved).""" def resolve(self, context: TestTimeContext) -> FlightInfo: diff --git a/monitoring/monitorlib/clients/flight_planning/planning.py b/monitoring/monitorlib/clients/flight_planning/planning.py index 0d7413fd0a..84eeb210c6 100644 --- a/monitoring/monitorlib/clients/flight_planning/planning.py +++ b/monitoring/monitorlib/clients/flight_planning/planning.py @@ -2,7 +2,7 @@ from enum import Enum -from implicitdict import ImplicitDict, StringBasedDateTime +from implicitdict import ImplicitDict, Optional, StringBasedDateTime from uas_standards.astm.f3548.v21 import api as f3548v21 from uas_standards.interuss.automated_testing.flight_planning.v1 import ( api as flight_planning_api, @@ -89,10 +89,10 @@ class PlanningActivityResponse(ImplicitDict): flight_plan_status: FlightPlanStatus """Status of the flight plan following the flight planning activity.""" - notes: str | None + notes: Optional[str] """Any human-readable notes regarding the activity.""" - includes_advisories: AdvisoryInclusion | None = AdvisoryInclusion.Unknown + includes_advisories: Optional[AdvisoryInclusion] = AdvisoryInclusion.Unknown def to_inject_flight_response(self) -> scd_api.InjectFlightResponse: if self.activity_result == PlanningActivityResult.Completed: @@ -141,7 +141,7 @@ class ClearAreaResponse(ImplicitDict): op_intent_removal_errors: dict[f3548v21.EntityOVN, dict] """When an error was encountered removing a particular operational intent reference, information about that error.""" - error: dict | None = None + error: Optional[dict] = None """If an error was encountered that could not be linked to a specific flight or operational intent, information about it will be populated here.""" @property diff --git a/monitoring/monitorlib/clients/flight_planning/test_preparation.py b/monitoring/monitorlib/clients/flight_planning/test_preparation.py index f9134956a7..c01ac7836e 100644 --- a/monitoring/monitorlib/clients/flight_planning/test_preparation.py +++ b/monitoring/monitorlib/clients/flight_planning/test_preparation.py @@ -1,13 +1,13 @@ -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.monitorlib.fetch import Query class ClearAreaOutcome(ImplicitDict): - success: bool | None = False + success: Optional[bool] = False """True if, and only if, all flight plans in the specified area managed by the USS were canceled and removed.""" - message: str | None + message: Optional[str] """If the USS was unable to clear the entire area, this message can provide information on the problem encountered.""" @@ -16,7 +16,7 @@ class ClearAreaResponse(ImplicitDict): class TestPreparationActivityResponse(ImplicitDict): - errors: list[str] | None = None + errors: Optional[list[str]] = None """If any errors occurred during this activity, a list of those errors.""" queries: list[Query] diff --git a/monitoring/monitorlib/clients/geospatial_info/querying.py b/monitoring/monitorlib/clients/geospatial_info/querying.py index 7880b67ab2..9162861eb8 100644 --- a/monitoring/monitorlib/clients/geospatial_info/querying.py +++ b/monitoring/monitorlib/clients/geospatial_info/querying.py @@ -1,6 +1,6 @@ from enum import Enum -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from uas_standards.interuss.automated_testing.geospatial_map.v1 import ( api as geospatial_map_api, ) @@ -27,18 +27,18 @@ class GeospatialFeatureFilter(ImplicitDict): # TODO: Add position - volumes4d: list[Volume4D] | None + volumes4d: Optional[list[Volume4D]] """If specified, only select geospatial features at least partially intersecting one or more of these volumes.""" # TODO: Add after & before - restriction_source: str | None + restriction_source: Optional[str] """If specified, only select geospatial features originating from the named source. The acceptable values for this field will be established by the test designers and will generally be used to limit responses to only the intended datasets under test even when the USS may have more additional geospatial features from other sources that may otherwise be relevant.""" - operation_rule_set: str | None + operation_rule_set: Optional[str] """If specified, only select geospatial features that would be relevant when planning an operation under the specified rule set. The acceptable values for this field will be established by the test designers and will generally correspond to sets of rules under which the system under test plans operations.""" - resulting_operational_impact: OperationalImpact | None + resulting_operational_impact: Optional[OperationalImpact] """If specified, only select geospatial features that would cause the specified outcome if a user attempted to plan a flight applicable to all the other criteria in this filter set.""" def to_geospatial_map(self) -> geospatial_map_api.GeospatialFeatureFilterSet: @@ -59,7 +59,7 @@ def to_geospatial_map(self) -> geospatial_map_api.GeospatialFeatureFilterSet: class GeospatialFeatureCheck(ImplicitDict): - filter_sets: list[GeospatialFeatureFilter] | None + filter_sets: Optional[list[GeospatialFeatureFilter]] """Select geospatial features which match any of the specified filter sets.""" def to_geospatial_map(self) -> geospatial_map_api.GeospatialMapCheck: @@ -88,7 +88,7 @@ class GeospatialFeatureCheckResult(ImplicitDict): features_selection_outcome: SelectionOutcome """Indication of whether one or more applicable geospatial features were selected according to the selection criteria of the corresponding check.""" - message: str | None + message: Optional[str] """A human-readable description of why the unsuccessful `features_selection_outcome` was reported. Should only be populated when appropriate according to the value of the `features_selection_outcome` field.""" diff --git a/monitoring/monitorlib/clients/mock_uss/mock_uss_scd_injection_api.py b/monitoring/monitorlib/clients/mock_uss/mock_uss_scd_injection_api.py index 526a157435..3a3bb15abb 100644 --- a/monitoring/monitorlib/clients/mock_uss/mock_uss_scd_injection_api.py +++ b/monitoring/monitorlib/clients/mock_uss/mock_uss_scd_injection_api.py @@ -1,4 +1,4 @@ -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from uas_standards.interuss.automated_testing.flight_planning.v1.api import ( UpsertFlightPlanRequest, ) @@ -29,10 +29,10 @@ class MockUssFlightBehavior(ImplicitDict): class MockUSSInjectFlightRequest(InjectFlightRequest): """InjectFlightRequest sent to mock_uss, which looks for the optional additional fields below.""" - behavior: MockUssFlightBehavior | None + behavior: Optional[MockUssFlightBehavior] class MockUSSUpsertFlightPlanRequest(UpsertFlightPlanRequest): """UpsertFlightPlanRequest sent to mock_uss, which looks for the optional additional fields below.""" - behavior: MockUssFlightBehavior | None + behavior: Optional[MockUssFlightBehavior] diff --git a/monitoring/monitorlib/fetch/__init__.py b/monitoring/monitorlib/fetch/__init__.py index 455c9417d8..71ff2f6c80 100644 --- a/monitoring/monitorlib/fetch/__init__.py +++ b/monitoring/monitorlib/fetch/__init__.py @@ -13,7 +13,7 @@ import requests import urllib3 import yaml -from implicitdict import ImplicitDict, StringBasedDateTime +from implicitdict import ImplicitDict, Optional, StringBasedDateTime from loguru import logger from yaml.representer import Representer @@ -47,12 +47,12 @@ class Settings: class RequestDescription(ImplicitDict): method: str url: str - headers: dict | None - json: dict | None = None - body: str | None = None + headers: Optional[dict] + json: Optional[dict] = None + body: Optional[str] = None - initiated_at: StringBasedDateTime | None - received_at: StringBasedDateTime | None + initiated_at: Optional[StringBasedDateTime] + received_at: Optional[StringBasedDateTime] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -139,13 +139,13 @@ def describe_request( class ResponseDescription(ImplicitDict): - code: int | None = None - failure: str | None - headers: dict | None + code: Optional[int] = None + failure: Optional[str] + headers: Optional[dict] elapsed_s: float reported: StringBasedDateTime - json: dict | None = None - body: str | None = None + json: Optional[dict] = None + body: Optional[str] = None def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -452,10 +452,10 @@ class Query(ImplicitDict): request: RequestDescription response: ResponseDescription - participant_id: str | None + participant_id: Optional[str] """If specified, identifier of the USS/participant hosting the server involved in this query.""" - query_type: QueryType | None + query_type: Optional[QueryType] """If specified, the recognized type of this query.""" @property diff --git a/monitoring/monitorlib/fetch/rid.py b/monitoring/monitorlib/fetch/rid.py index 209b5d0273..f652a5ad75 100644 --- a/monitoring/monitorlib/fetch/rid.py +++ b/monitoring/monitorlib/fetch/rid.py @@ -5,7 +5,7 @@ import s2sphere import yaml -from implicitdict import ImplicitDict, StringBasedDateTime +from implicitdict import ImplicitDict, Optional, StringBasedDateTime from uas_standards.ansi_cta_2063_a import SerialNumber from uas_standards.astm.f3411 import v19, v22a from uas_standards.astm.f3411.v22a.api import ( @@ -24,8 +24,8 @@ class ISA(ImplicitDict): """Version-independent representation of a F3411 identification service area.""" - v19_value: v19.api.IdentificationServiceArea | None = None - v22a_value: v22a.api.IdentificationServiceArea | None = None + v19_value: Optional[v19.api.IdentificationServiceArea] = None + v22a_value: Optional[v22a.api.IdentificationServiceArea] = None @property def rid_version(self) -> RIDVersion: @@ -152,16 +152,16 @@ class Position(ImplicitDict): time: datetime.datetime """Timestamp for the position.""" - height: RIDHeight | None + height: Optional[RIDHeight] - accuracy_v: ( - VerticalAccuracy | None - ) # Note: we use the enum defined in the v2 API as it is equivalent (and thus compatible) to the v19 one + accuracy_v: Optional[ + VerticalAccuracy + ] # Note: we use the enum defined in the v2 API as it is equivalent (and thus compatible) to the v19 one """Vertical error that is likely to be present in this reported position""" - accuracy_h: ( - HorizontalAccuracy | None - ) # Note: we use the enum defined in the v2 API as it is equivalent (and thus compatible) to the v19 one + accuracy_h: Optional[ + HorizontalAccuracy + ] # Note: we use the enum defined in the v2 API as it is equivalent (and thus compatible) to the v19 one """Horizontal error that is likely to be present in this reported position.""" @staticmethod @@ -198,8 +198,8 @@ def from_v22a_rid_aircraft_position( class Flight(ImplicitDict): """Version-independent representation of a F3411 flight.""" - v19_value: v19.api.RIDFlight | None = None - v22a_value: v22a.api.RIDFlight | None = None + v19_value: Optional[v19.api.RIDFlight] = None + v22a_value: Optional[v22a.api.RIDFlight] = None @property def rid_version(self) -> RIDVersion: @@ -488,8 +488,8 @@ def errors(self) -> list[str]: class FlightDetails(ImplicitDict): """Version-independent representation of details for a F3411 flight.""" - v19_value: v19.api.RIDFlightDetails | None = None - v22a_value: v22a.api.RIDFlightDetails | None = None + v19_value: Optional[v19.api.RIDFlightDetails] = None + v22a_value: Optional[v22a.api.RIDFlightDetails] = None @property def rid_version(self) -> RIDVersion: @@ -673,8 +673,8 @@ def registration_id( class Subscription(ImplicitDict): """Version-independent representation of a F3411 subscription.""" - v19_value: v19.api.Subscription | None = None - v22a_value: v22a.api.Subscription | None = None + v19_value: Optional[v19.api.Subscription] = None + v22a_value: Optional[v22a.api.Subscription] = None @property def duration(self) -> datetime.timedelta | None: @@ -793,8 +793,8 @@ def owner(self) -> str: class RIDQuery(ImplicitDict): - v19_query: Query | None = None - v22a_query: Query | None = None + v19_query: Optional[Query] = None + v22a_query: Optional[Query] = None @property def rid_version(self) -> RIDVersion: diff --git a/monitoring/monitorlib/fetch/scd.py b/monitoring/monitorlib/fetch/scd.py index e64fce1999..5bfc855008 100644 --- a/monitoring/monitorlib/fetch/scd.py +++ b/monitoring/monitorlib/fetch/scd.py @@ -2,7 +2,7 @@ import s2sphere import yaml -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from uas_standards.astm.f3548.v21.api import ( OPERATIONS, OperationID, @@ -21,7 +21,7 @@ class FetchedEntityReferences(fetch.Query): """Wrapper to interpret a DSS Entity query as a set of Entity references.""" - entity_type: str | None = None + entity_type: Optional[str] = None @property def success(self) -> bool: @@ -125,8 +125,8 @@ def operational_intent_references( class FetchedEntity(fetch.Query): - id_requested: str | None = None - entity_type: str | None = None + id_requested: Optional[str] = None + entity_type: Optional[str] = None @property def success(self) -> bool: diff --git a/monitoring/monitorlib/geo.py b/monitoring/monitorlib/geo.py index 098b4a4112..db205bebf9 100644 --- a/monitoring/monitorlib/geo.py +++ b/monitoring/monitorlib/geo.py @@ -8,7 +8,7 @@ import pyproj import s2sphere import shapely.geometry -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from s2sphere import LatLng from scipy.interpolate import RectBivariateSpline as Spline from uas_standards.astm.f3411.v19 import api as f3411v19 @@ -110,7 +110,7 @@ def in_meters(self) -> float: class Polygon(ImplicitDict): - vertices: list[LatLngPoint] | None + vertices: Optional[list[LatLngPoint]] def vertex_average(self) -> LatLngPoint: lat = sum(p.lat for p in self.vertices) / len(self.vertices) @@ -226,10 +226,10 @@ def from_f3548v21(vol: f3548v21.Altitude | dict) -> Altitude: class Volume3D(ImplicitDict): - outline_circle: Circle | None = None - outline_polygon: Polygon | None = None - altitude_lower: Altitude | None = None - altitude_upper: Altitude | None = None + outline_circle: Optional[Circle] = None + outline_polygon: Optional[Polygon] = None + altitude_lower: Optional[Altitude] = None + altitude_upper: Optional[Altitude] = None def altitude_lower_wgs84_m(self, default_value: float | None = None) -> float: if self.altitude_lower is None: diff --git a/monitoring/monitorlib/geotemporal.py b/monitoring/monitorlib/geotemporal.py index 5059443e85..bf08cc224c 100644 --- a/monitoring/monitorlib/geotemporal.py +++ b/monitoring/monitorlib/geotemporal.py @@ -4,7 +4,7 @@ from datetime import datetime, timedelta import s2sphere as s2sphere -from implicitdict import ImplicitDict, StringBasedTimeDelta +from implicitdict import ImplicitDict, Optional, StringBasedTimeDelta from uas_standards.astm.f3548.v21 import api as f3548v21 from uas_standards.interuss.automated_testing.flight_planning.v1 import api as fp_api from uas_standards.interuss.automated_testing.geospatial_map.v1 import ( @@ -23,28 +23,28 @@ class Volume4DTemplate(ImplicitDict): - outline_polygon: Polygon | None = None + outline_polygon: Optional[Polygon] = None """Polygonal 2D outline/footprint of the specified area. May not be defined if outline_circle is defined.""" - outline_circle: Circle | None = None + outline_circle: Optional[Circle] = None """Circular outline/footprint of the specified area. May not be defined if outline_polygon is defined.""" - start_time: TestTime | None = None + start_time: Optional[TestTime] = None """The time at which the virtual user may start using the specified geospatial area for their flight. May not be defined if duration and end_time are defined.""" - end_time: TestTime | None = None + end_time: Optional[TestTime] = None """The time at which the virtual user will be finished using the specified geospatial area for their flight. May not be defined if duration and start_time are defined.""" - duration: StringBasedTimeDelta | None = None + duration: Optional[StringBasedTimeDelta] = None """If only one of start_time and end_time is specified, then the other time should be separated from the specified time by this amount. May not be defined in both start_time and end_time are defined.""" - altitude_lower: Altitude | None = None + altitude_lower: Optional[Altitude] = None """The minimum altitude at which the virtual user will fly while using this volume for their flight.""" - altitude_upper: Altitude | None = None + altitude_upper: Optional[Altitude] = None """The maximum altitude at which the virtual user will fly while using this volume for their flight.""" - transformations: list[Transformation] | None = None + transformations: Optional[list[Transformation]] = None """If specified, transform this volume according to these transformations in order.""" def _get_volume(self) -> Volume3D: @@ -118,8 +118,8 @@ class Volume4D(ImplicitDict): """Generic representation of a 4D volume, usable across multiple standards and formats.""" volume: Volume3D - time_start: Time | None = None - time_end: Time | None = None + time_start: Optional[Time] = None + time_end: Optional[Time] = None def offset_time(self, dt: timedelta) -> Volume4D: kwargs = {"volume": self.volume} diff --git a/monitoring/monitorlib/idempotency.py b/monitoring/monitorlib/idempotency.py index ebff7b6088..b4c4820fcc 100644 --- a/monitoring/monitorlib/idempotency.py +++ b/monitoring/monitorlib/idempotency.py @@ -6,7 +6,7 @@ import arrow import flask -from implicitdict import ImplicitDict, StringBasedDateTime +from implicitdict import ImplicitDict, Optional, StringBasedDateTime from loguru import logger from monitoring.monitorlib.multiprocessing import SynchronizedValue @@ -21,8 +21,8 @@ class Response(ImplicitDict): Note that this object is never actually used (in order to maximize performance); instead it serves as documentation of the structure of the fields within a plain JSON dict/object.""" - json: dict | None - body: str | None + json: Optional[dict] + body: Optional[str] code: int timestamp: StringBasedDateTime diff --git a/monitoring/monitorlib/mutate/rid.py b/monitoring/monitorlib/mutate/rid.py index c6f3d0a459..f88c815b7b 100644 --- a/monitoring/monitorlib/mutate/rid.py +++ b/monitoring/monitorlib/mutate/rid.py @@ -7,7 +7,7 @@ import uas_standards.astm.f3411.v22a.api as v22a_api import uas_standards.astm.f3411.v22a.constants as v22a_constants import yaml -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from uas_standards import Operation from yaml.representer import Representer @@ -20,7 +20,7 @@ class ChangedSubscription(RIDQuery): """Version-independent representation of a subscription following a change in the DSS.""" - mutation: str | None = None + mutation: Optional[str] = None @property def _v19_response(self) -> v19_api.PutSubscriptionResponse: @@ -238,8 +238,8 @@ def errors(self) -> list[str]: class SubscriberToNotify(ImplicitDict): """Version-independent representation of a subscriber to notify of a change in the DSS.""" - v19_value: v19_api.SubscriberToNotify | None = None - v22a_value: v22a_api.SubscriberToNotify | None = None + v19_value: Optional[v19_api.SubscriberToNotify] = None + v22a_value: Optional[v22a_api.SubscriberToNotify] = None @property def rid_version(self) -> RIDVersion: @@ -323,7 +323,7 @@ def url(self) -> str: class ChangedISA(RIDQuery): """Version-independent representation of a changed F3411 identification service area.""" - mutation: str | None = None + mutation: Optional[str] = None @property def _v19_response( diff --git a/monitoring/monitorlib/mutate/scd.py b/monitoring/monitorlib/mutate/scd.py index 2f6a4b9259..5db457327d 100644 --- a/monitoring/monitorlib/mutate/scd.py +++ b/monitoring/monitorlib/mutate/scd.py @@ -2,7 +2,7 @@ import s2sphere import yaml -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from uas_standards.astm.f3548.v21.api import ( OPERATIONS, OperationalIntentReference, @@ -19,7 +19,7 @@ class MutatedSubscription(fetch.Query): - mutation: str | None = None + mutation: Optional[str] = None @property def success(self) -> bool: diff --git a/monitoring/monitorlib/rid_automated_testing/injection_api.py b/monitoring/monitorlib/rid_automated_testing/injection_api.py index ef346f2385..866f5e62e4 100644 --- a/monitoring/monitorlib/rid_automated_testing/injection_api.py +++ b/monitoring/monitorlib/rid_automated_testing/injection_api.py @@ -2,6 +2,7 @@ import arrow import s2sphere +from implicitdict import Optional from uas_standards.interuss.automated_testing.rid.v1 import injection from uas_standards.interuss.automated_testing.rid.v1.injection import ( UASID, @@ -30,7 +31,7 @@ class TestFlight(injection.TestFlight): - raw_telemetry: list[RIDAircraftState] | None + raw_telemetry: Optional[list[RIDAircraftState]] """Copy of original telemetry with potential invalid data""" def __init__(self, *args, **kwargs): diff --git a/monitoring/monitorlib/subscription_params.py b/monitoring/monitorlib/subscription_params.py index 5be3ffbece..3310a176e1 100644 --- a/monitoring/monitorlib/subscription_params.py +++ b/monitoring/monitorlib/subscription_params.py @@ -3,7 +3,7 @@ import datetime import s2sphere -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from uas_standards.astm.f3548.v21.api import PutSubscriptionParameters from monitoring.monitorlib.geo import LatLngPoint @@ -21,13 +21,13 @@ class SubscriptionParams(ImplicitDict): area_vertices: list[LatLngPoint] """List of vertices of a polygon defining the area of interest""" - min_alt_m: float | None + min_alt_m: Optional[float] """Minimum altitude in meters""" - max_alt_m: float | None + max_alt_m: Optional[float] """Maximum altitude in meters""" - start_time: datetime.datetime | None = None + start_time: Optional[datetime.datetime] = None """Start time of subscription""" end_time: datetime.datetime diff --git a/monitoring/monitorlib/temporal.py b/monitoring/monitorlib/temporal.py index 599bac7752..9492e13bca 100644 --- a/monitoring/monitorlib/temporal.py +++ b/monitoring/monitorlib/temporal.py @@ -4,7 +4,12 @@ from enum import Enum import arrow -from implicitdict import ImplicitDict, StringBasedDateTime, StringBasedTimeDelta +from implicitdict import ( + ImplicitDict, + Optional, + StringBasedDateTime, + StringBasedTimeDelta, +) from pvlib.solarposition import get_solarposition from uas_standards.astm.f3548.v21 import api as f3548v21 @@ -58,7 +63,7 @@ class NextDay(ImplicitDict): * "-08:00" (ISO time zone) * "US/Pacific" (IANA time zone)""" - days_of_the_week: list[DayOfTheWeek] | None = None + days_of_the_week: Optional[list[DayOfTheWeek]] = None """Acceptable days of the week. Omit to indicate that any day of the week is acceptable.""" @@ -131,28 +136,28 @@ def all_times_are(t: Time) -> TestTimeContext: class TestTime(ImplicitDict): """Exactly one of the time option fields of this object must be specified.""" - absolute_time: StringBasedDateTime | None = None + absolute_time: Optional[StringBasedDateTime] = None """Time option field to use a precise timestamp which does not change with test conditions. The value of absolute_time is limited given that the specific time a test will be started is unknown, and the jurisdictions usually impose a limit on how far in the future an operation can be planned. """ - time_during_test: TimeDuringTest | None = None + time_during_test: Optional[TimeDuringTest] = None """Time option field to, if specified, use a timestamp relating to the current test run.""" - name: TimeDuringTest | None + name: Optional[TimeDuringTest] """If specified, update the TestTimeContext with the time computed for this TestTime as this name, which may then later be referenced by a different TestTime via time_during_test.""" - next_day: NextDay | None = None + next_day: Optional[NextDay] = None """Time option field to use a timestamp equal to midnight beginning the next occurrence of any matching day following the specified reference timestamp.""" - next_sun_position: NextSunPosition | None = None + next_sun_position: Optional[NextSunPosition] = None """Time option field to use a timestamp equal to the next time after the specified reference timestamp at which the sun will be at the specified angle above the horizon.""" - offset_from: OffsetTime | None = None + offset_from: Optional[OffsetTime] = None """Time option field to use a timestamp that is offset by the specified amount from the specified time.""" - use_timezone: str | None = None + use_timezone: Optional[str] = None """If specified, report the timestamp in the specified time zone. Examples: * "local" (local time of machine running this code) * "Z" (Zulu time) diff --git a/monitoring/monitorlib/transformations.py b/monitoring/monitorlib/transformations.py index 0867d87ede..7d4e67fde4 100644 --- a/monitoring/monitorlib/transformations.py +++ b/monitoring/monitorlib/transformations.py @@ -1,22 +1,22 @@ -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional class RelativeTranslation(ImplicitDict): """Offset a geo feature by a particular amount.""" - meters_east: float | None + meters_east: Optional[float] """Number of meters east to translate.""" - meters_north: float | None + meters_north: Optional[float] """Number of meters north to translate.""" - meters_up: float | None + meters_up: Optional[float] """Number of meters upward to translate.""" - degrees_east: float | None + degrees_east: Optional[float] """Number of degrees of longitude east to translate.""" - degrees_north: float | None + degrees_north: Optional[float] """Number of degrees of latitude north to translate.""" @@ -33,6 +33,6 @@ class AbsoluteTranslation(ImplicitDict): class Transformation(ImplicitDict): """A transformation to apply to a geotemporal feature. Exactly one field must be specified.""" - relative_translation: RelativeTranslation | None + relative_translation: Optional[RelativeTranslation] - absolute_translation: AbsoluteTranslation | None + absolute_translation: Optional[AbsoluteTranslation] diff --git a/monitoring/uss_qualifier/action_generators/documentation/definitions.py b/monitoring/uss_qualifier/action_generators/documentation/definitions.py index 76cb03d772..a58e4b5b8f 100644 --- a/monitoring/uss_qualifier/action_generators/documentation/definitions.py +++ b/monitoring/uss_qualifier/action_generators/documentation/definitions.py @@ -1,4 +1,4 @@ -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.uss_qualifier.action_generators.definitions import GeneratorTypeName from monitoring.uss_qualifier.scenarios.definitions import TestScenarioTypeName @@ -15,10 +15,10 @@ class PotentialTestScenarioAction(ImplicitDict): class PotentialTestSuiteAction(ImplicitDict): - suite_type: TestSuiteTypeName | None + suite_type: Optional[TestSuiteTypeName] """Type/location of test suite. Usually expressed as the file name of the suite definition (without extension) qualified relative to the `uss_qualifier` folder""" - suite_definition: TestSuiteDefinition | None + suite_definition: Optional[TestSuiteDefinition] """Definition of test suite internal to the configuration -- specified instead of `suite_type`.""" @@ -31,9 +31,9 @@ class PotentialActionGeneratorAction(ImplicitDict): class PotentialGeneratedAction(ImplicitDict): - test_scenario: PotentialTestScenarioAction | None - test_suite: PotentialTestSuiteAction | None - action_generator: PotentialActionGeneratorAction | None + test_scenario: Optional[PotentialTestScenarioAction] + test_suite: Optional[PotentialTestSuiteAction] + action_generator: Optional[PotentialActionGeneratorAction] def get_action_type(self) -> ActionType: matches = [v for v in ActionType if v in self and self[v]] diff --git a/monitoring/uss_qualifier/action_generators/flight_planning/planner_combinations.py b/monitoring/uss_qualifier/action_generators/flight_planning/planner_combinations.py index 2ec548db50..cf171c8872 100644 --- a/monitoring/uss_qualifier/action_generators/flight_planning/planner_combinations.py +++ b/monitoring/uss_qualifier/action_generators/flight_planning/planner_combinations.py @@ -1,6 +1,6 @@ from collections.abc import Iterator -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.monitorlib.inspection import fullname from monitoring.uss_qualifier.action_generators.documentation.definitions import ( @@ -30,7 +30,7 @@ class FlightPlannerCombinationsSpecification(ImplicitDict): flight_planners_source: ResourceID """ID of the resource providing all available flight planners""" - combination_selector_source: ResourceID | None = None + combination_selector_source: Optional[ResourceID] = None """If specified and contained in the provided resources, the resource containing a FlightPlannerCombinationSelectorResource to select only a subset of combinations""" roles: list[ResourceID] diff --git a/monitoring/uss_qualifier/configurations/configuration.py b/monitoring/uss_qualifier/configurations/configuration.py index 3c88d6a37c..f1795da9fd 100644 --- a/monitoring/uss_qualifier/configurations/configuration.py +++ b/monitoring/uss_qualifier/configurations/configuration.py @@ -1,6 +1,6 @@ from __future__ import annotations -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.monitorlib.dicts import JSONAddress from monitoring.uss_qualifier.action_generators.definitions import GeneratorTypeName @@ -20,13 +20,13 @@ class InstanceIndexRange(ImplicitDict): - lo: int | None + lo: Optional[int] """If specified, no indices lower than this value will be included in the range.""" - i: int | None + i: Optional[int] """If specified, no index other than this one will be included in the range.""" - hi: int | None + hi: Optional[int] """If specified, no indices higher than this value will be included in the range.""" def includes(self, i: int) -> bool: @@ -42,21 +42,21 @@ def includes(self, i: int) -> bool: class ActionGeneratorSelectionCondition(ImplicitDict): """By default, select all action generators. When specified, limit selection to specified conditions.""" - types: list[GeneratorTypeName] | None + types: Optional[list[GeneratorTypeName]] """Only select action generators of the specified types.""" class TestSuiteSelectionCondition(ImplicitDict): """By default, select all test suites. When specified, limit selection to specified conditions.""" - types: list[TestSuiteTypeName] | None + types: Optional[list[TestSuiteTypeName]] """Only select test suites of the specified types.""" class TestScenarioSelectionCondition(ImplicitDict): """By default, select all test scenarios. When specified, limit selection to specified conditions.""" - types: list[TestScenarioTypeName] | None + types: Optional[list[TestScenarioTypeName]] """Only select test scenarios of the specified types.""" @@ -73,7 +73,7 @@ class NthInstanceCondition(ImplicitDict): class AncestorSelectionCondition(ImplicitDict): """Select ancestor actions meeting all the specified conditions.""" - of_generation: int | None + of_generation: Optional[int] """The ancestor is exactly this many generations removed (1 = parent, 2 = grandparent, etc). If not specified, an ancestor of any generation meeting the `which` conditions will be selected.""" @@ -88,19 +88,19 @@ class TestSuiteActionSelectionCondition(ImplicitDict): If more than one subcondition is specified, satisfaction of ALL subconditions are necessary to select the action. """ - is_action_generator: ActionGeneratorSelectionCondition | None + is_action_generator: Optional[ActionGeneratorSelectionCondition] """Select these action generator actions.""" - is_test_suite: TestSuiteSelectionCondition | None + is_test_suite: Optional[TestSuiteSelectionCondition] """Select these test suite actions.""" - is_test_scenario: TestScenarioSelectionCondition | None + is_test_scenario: Optional[TestScenarioSelectionCondition] """Select these test scenario actions.""" - regex_matches_name: str | None + regex_matches_name: Optional[str] """Select actions where this regular expression has a match in the action's name.""" - defined_at: list[JSONAddress] | None + defined_at: Optional[list[JSONAddress]] """Select actions defined at one of the specified addresses. The top-level action in a test run is 'test_scenario', 'test_suite', or 'action_generator'. Children use the @@ -109,27 +109,27 @@ class TestSuiteActionSelectionCondition(ImplicitDict): 'action_generator.actions[1].test_suite.actions[2].test_scenario'. An address that starts or ends with 'actions[i]' is invalid and will never match.""" - nth_instance: NthInstanceCondition | None + nth_instance: Optional[NthInstanceCondition] """Select only certain instances of matching actions.""" - has_ancestor: AncestorSelectionCondition | None + has_ancestor: Optional[AncestorSelectionCondition] """Select only actions with a matching ancestor.""" - except_when: list[TestSuiteActionSelectionCondition] | None + except_when: Optional[list[TestSuiteActionSelectionCondition]] """Do not select actions selected by any of these conditions, even when they are selected by one or more conditions above.""" class ExecutionConfiguration(ImplicitDict): - include_action_when: list[TestSuiteActionSelectionCondition] | None = None + include_action_when: Optional[list[TestSuiteActionSelectionCondition]] = None """If specified, only execute test actions if they are selected by ANY of these conditions (and not selected by any of the `skip_when` conditions).""" - skip_action_when: list[TestSuiteActionSelectionCondition] | None = None + skip_action_when: Optional[list[TestSuiteActionSelectionCondition]] = None """If specified, do not execute test actions if they are selected by ANY of these conditions.""" - stop_fast: bool | None = False + stop_fast: Optional[bool] = False """If true, escalate the Severity of any failed check to Critical in order to end the test run early.""" - stop_when_resource_not_created: bool | None = False + stop_when_resource_not_created: Optional[bool] = False """If true, stop test execution if one of the resources cannot be created. Otherwise, resources that cannot be created due to missing prerequisites are simply treated as omitted.""" @@ -137,13 +137,13 @@ class TestConfiguration(ImplicitDict): action: TestSuiteActionDeclaration """The action this test configuration wants to run (usually a test suite)""" - non_baseline_inputs: list[JSONAddress] | None = None + non_baseline_inputs: Optional[list[JSONAddress]] = None """List of portions of the configuration that should not be considered when computing the test baseline signature (e.g., environmental definitions).""" resources: ResourceCollection """Declarations for resources used by the test suite""" - execution: ExecutionConfiguration | None + execution: Optional[ExecutionConfiguration] """Specification for how to execute the test run.""" @@ -155,20 +155,20 @@ class TestedRequirementsConfiguration(ImplicitDict): report_name: str """Name of subfolder in output path to contain the rendered templated report""" - requirement_collections: ( - dict[TestedRequirementsCollectionIdentifier, RequirementCollection] | None - ) + requirement_collections: Optional[ + dict[TestedRequirementsCollectionIdentifier, RequirementCollection] + ] """Definition of requirement collections specific to production of this artifact.""" - aggregate_participants: dict[ParticipantID, list[ParticipantID]] | None + aggregate_participants: Optional[dict[ParticipantID, list[ParticipantID]]] """If specified, a list of 'aggregate participants', each of which is composed of multiple test participants. If specified, these aggregate participants are the preferred subject for `participant_requirements`. """ - participant_requirements: ( - dict[ParticipantID, TestedRequirementsCollectionIdentifier | None] | None - ) + participant_requirements: Optional[ + dict[ParticipantID, TestedRequirementsCollectionIdentifier | None] + ] """If a requirement collection is specified for a participant, only the requirements in the specified collection will be listed on that participant's report. If a requirement collection is specified as None/null for a participant, all potentially-testable requirements will be included. @@ -201,7 +201,7 @@ class TemplatedReportConfiguration(ImplicitDict): report_name: str """Name of HTML file (without extension) to contain the rendered templated report""" - configuration: TemplatedReportInjectedConfiguration | None = None + configuration: Optional[TemplatedReportInjectedConfiguration] = None """Configuration to be injected in the templated report""" @@ -209,7 +209,7 @@ class RawReportConfiguration(ImplicitDict): redact_access_tokens: bool = True """When True, look for instances of "Authorization" keys in the report with values starting "Bearer " and redact the signature from those access tokens""" - indent: int | None = None + indent: Optional[int] = None """To pretty-print JSON content, specify an indent level (generally 2), or omit or set to None to write compactly.""" @@ -219,36 +219,36 @@ class GloballyExpandedReportConfiguration(ImplicitDict): class ArtifactsConfiguration(ImplicitDict): - raw_report: RawReportConfiguration | None = None + raw_report: Optional[RawReportConfiguration] = None """Configuration for raw report generation""" - report_html: ReportHTMLConfiguration | None = None + report_html: Optional[ReportHTMLConfiguration] = None """If specified, configuration describing how an HTML version of the raw report should be generated""" - templated_reports: list[TemplatedReportConfiguration] | None = None + templated_reports: Optional[list[TemplatedReportConfiguration]] = None """List of report templates to be rendered""" - tested_requirements: list[TestedRequirementsConfiguration] | None = None + tested_requirements: Optional[list[TestedRequirementsConfiguration]] = None """If specified, list of configurations describing desired reports summarizing tested requirements for each participant""" - sequence_view: SequenceViewConfiguration | None = None + sequence_view: Optional[SequenceViewConfiguration] = None """If specified, configuration describing a desired report describing the sequence of events that occurred during the test""" - globally_expanded_report: GloballyExpandedReportConfiguration | None = None + globally_expanded_report: Optional[GloballyExpandedReportConfiguration] = None """If specified, configuration describing a desired report mimicking what might be seen had the test run been conducted manually.""" class USSQualifierConfigurationV1(ImplicitDict): - test_run: TestConfiguration | None = None + test_run: Optional[TestConfiguration] = None """If specified, configuration describing how to perform a test run""" - artifacts: ArtifactsConfiguration | None = None + artifacts: Optional[ArtifactsConfiguration] = None """If specified, configuration describing the artifacts related to the test run""" - validation: ValidationConfiguration | None = None + validation: Optional[ValidationConfiguration] = None """If specified, configuration describing how to validate the output report (and return an error code if validation fails)""" class USSQualifierConfiguration(ImplicitDict): - v1: USSQualifierConfigurationV1 | None + v1: Optional[USSQualifierConfigurationV1] """Configuration in version 1 format""" diff --git a/monitoring/uss_qualifier/main.py b/monitoring/uss_qualifier/main.py index c387e7b1a6..923bf35dc6 100644 --- a/monitoring/uss_qualifier/main.py +++ b/monitoring/uss_qualifier/main.py @@ -6,7 +6,7 @@ import sys import yaml -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from loguru import logger from monitoring.monitorlib.dicts import get_element_or_default, remove_elements @@ -87,8 +87,8 @@ class TestDefinitionDescription(ImplicitDict): codebase_version: str commit_hash: str - baseline_signature: str | None = None - environment_signature: str | None = None + baseline_signature: Optional[str] = None + environment_signature: Optional[str] = None def sign(self, whole_config: USSQualifierConfiguration) -> None: logger.debug("Computing signatures of inputs") diff --git a/monitoring/uss_qualifier/reports/capability_definitions.py b/monitoring/uss_qualifier/reports/capability_definitions.py index 5fbdafe098..a21e715894 100644 --- a/monitoring/uss_qualifier/reports/capability_definitions.py +++ b/monitoring/uss_qualifier/reports/capability_definitions.py @@ -1,6 +1,6 @@ from __future__ import annotations -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.uss_qualifier.requirements.definitions import RequirementCollection @@ -60,7 +60,7 @@ class CapabilityVerifiedCondition(SpecificCondition): capability_ids: list[CapabilityID] """List of identifier of capability that must be verified for this condition to be satisfied.""" - capability_location: JSONPathExpression | None + capability_location: Optional[JSONPathExpression] """Location of report to inspect for the verification of the specified capability, relative to the report in which the capability is defined. Implicit default value is "$" (look for verified capability in the report in which the dependant capability is defined). @@ -83,11 +83,11 @@ class CapabilityVerificationCondition(ImplicitDict): Exactly one field must be specified.""" - all_conditions: AllConditions | None - any_conditions: AnyCondition | None - no_failed_checks: NoFailedChecksCondition | None - requirements_checked: RequirementsCheckedCondition | None - capability_verified: CapabilityVerifiedCondition | None + all_conditions: Optional[AllConditions] + any_conditions: Optional[AnyCondition] + no_failed_checks: Optional[NoFailedChecksCondition] + requirements_checked: Optional[RequirementsCheckedCondition] + capability_verified: Optional[CapabilityVerifiedCondition] class ParticipantCapabilityDefinition(ImplicitDict): diff --git a/monitoring/uss_qualifier/reports/report.py b/monitoring/uss_qualifier/reports/report.py index 815a649247..af998e1aa0 100644 --- a/monitoring/uss_qualifier/reports/report.py +++ b/monitoring/uss_qualifier/reports/report.py @@ -4,7 +4,7 @@ from datetime import UTC, datetime from typing import Any -from implicitdict import ImplicitDict, StringBasedDateTime +from implicitdict import ImplicitDict, Optional, StringBasedDateTime from monitoring.monitorlib import fetch, inspection from monitoring.monitorlib.errors import stacktrace_string @@ -50,10 +50,10 @@ class FailedCheck(ImplicitDict): participants: list[ParticipantID] """Participants that may not meet the relevant requirements due to this failed check""" - query_report_timestamps: list[str] | None + query_report_timestamps: Optional[list[str]] """List of the `report` timestamp field for queries relevant to this failed check""" - additional_data: dict | None + additional_data: Optional[dict] """Additional data, structured according to the checks' needs, that may be relevant for understanding this failed check""" @@ -81,7 +81,7 @@ class TestStepReport(ImplicitDict): start_time: StringBasedDateTime """Time at which the test step started""" - queries: list[fetch.Query] | None + queries: Optional[list[fetch.Query]] """Description of HTTP requests relevant to this issue""" failed_checks: list[FailedCheck] @@ -90,7 +90,7 @@ class TestStepReport(ImplicitDict): passed_checks: list[PassedCheck] """The checks which successfully passed in this test step""" - end_time: StringBasedDateTime | None + end_time: Optional[StringBasedDateTime] """Time at which the test step completed or encountered an error""" def has_critical_problem(self) -> bool: @@ -149,7 +149,7 @@ class TestCaseReport(ImplicitDict): start_time: StringBasedDateTime """Time at which the test case started""" - end_time: StringBasedDateTime | None + end_time: Optional[StringBasedDateTime] """Time at which the test case completed or encountered an error""" steps: list[TestStepReport] @@ -223,16 +223,16 @@ class TestScenarioReport(ImplicitDict): documentation_url: str """URL at which this test scenario is described""" - resource_origins: dict[ResourceID, str] | None + resource_origins: Optional[dict[ResourceID, str]] """For each resource used by this test scenario, the place that resource originated.""" - notes: dict[str, Note] | None + notes: Optional[dict[str, Note]] """Additional information about this scenario that may be useful""" start_time: StringBasedDateTime """Time at which the test scenario started""" - end_time: StringBasedDateTime | None + end_time: Optional[StringBasedDateTime] """Time at which the test scenario completed or encountered an error""" successful: bool = False @@ -241,10 +241,10 @@ class TestScenarioReport(ImplicitDict): cases: list[TestCaseReport] """Reports for each of the test cases in this test scenario, in chronological order.""" - cleanup: TestStepReport | None + cleanup: Optional[TestStepReport] """If this test scenario performed cleanup, this report captures the relevant information.""" - execution_error: ErrorReport | None + execution_error: Optional[ErrorReport] """If there was an error while executing this test scenario, this field describes the error""" def has_critical_problem(self) -> bool: @@ -317,7 +317,7 @@ class ActionGeneratorReport(ImplicitDict): actions: list[TestSuiteActionReport] """Reports from the actions generated by the action generator, in order of execution.""" - end_time: StringBasedDateTime | None + end_time: Optional[StringBasedDateTime] """Time at which the action generator completed or encountered an error""" successful: bool = False @@ -360,16 +360,16 @@ def participant_ids(self) -> set[ParticipantID]: class TestSuiteActionReport(ImplicitDict): - test_suite: TestSuiteReport | None + test_suite: Optional[TestSuiteReport] """If this action was a test suite, this field will hold its report""" - test_scenario: TestScenarioReport | None + test_scenario: Optional[TestScenarioReport] """If this action was a test scenario, this field will hold its report""" - action_generator: ActionGeneratorReport | None + action_generator: Optional[ActionGeneratorReport] """If this action was an action generator, this field will hold its report""" - skipped_action: SkippedActionReport | None + skipped_action: Optional[SkippedActionReport] """If this action was skipped, this field will hold its report""" def get_applicable_report(self) -> tuple[bool, bool, bool]: @@ -594,19 +594,19 @@ class ParticipantCapabilityConditionEvaluationReport(ImplicitDict): condition_satisfied: bool """Whether the condition was satisfied for the relevant participant.""" - all_conditions: AllConditionsEvaluationReport | None + all_conditions: Optional[AllConditionsEvaluationReport] """When specified, the condition evaluated was AllConditions.""" - any_conditions: AnyConditionEvaluationReport | None + any_conditions: Optional[AnyConditionEvaluationReport] """When specified, the condition evaluated was AnyCondition.""" - no_failed_checks: NoFailedChecksConditionEvaluationReport | None + no_failed_checks: Optional[NoFailedChecksConditionEvaluationReport] """When specified, the condition evaluated was NoFailedChecksCondition.""" - requirements_checked: RequirementsCheckedConditionEvaluationReport | None + requirements_checked: Optional[RequirementsCheckedConditionEvaluationReport] """When specified, the condition evaluated was RequirementsCheckedCondition.""" - capability_verified: CapabilityVerifiedConditionEvaluationReport | None + capability_verified: Optional[CapabilityVerifiedConditionEvaluationReport] """When specified, the condition evaluated was CapabilityVerifiedCondition.""" @@ -675,7 +675,7 @@ class TestSuiteReport(ImplicitDict): actions: list[TestSuiteActionReport] """Reports from test scenarios and test suites comprising the test suite for this report, in order of execution.""" - end_time: StringBasedDateTime | None + end_time: Optional[StringBasedDateTime] """Time at which the test suite completed""" successful: bool = False @@ -743,7 +743,7 @@ class TestRunReport(ImplicitDict): report: TestSuiteActionReport """Report produced by configured test action""" - runtime_metadata: dict | None + runtime_metadata: Optional[dict] """Metadata for the test run specified at runtime.""" diff --git a/monitoring/uss_qualifier/reports/sequence_view/summary_types.py b/monitoring/uss_qualifier/reports/sequence_view/summary_types.py index 8a18cd71a4..861da638c0 100644 --- a/monitoring/uss_qualifier/reports/sequence_view/summary_types.py +++ b/monitoring/uss_qualifier/reports/sequence_view/summary_types.py @@ -4,7 +4,7 @@ from datetime import datetime from enum import Enum -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.monitorlib.fetch import Query from monitoring.uss_qualifier.configurations.configuration import ParticipantID @@ -32,11 +32,11 @@ class EventType(str, Enum): class Event(ImplicitDict): event_index: int = 0 - passed_check: PassedCheck | None = None - failed_check: FailedCheck | None = None - query_events: list[Event | str] | None = None - query: Query | None = None - note: NoteEvent | None = None + passed_check: Optional[PassedCheck] = None + failed_check: Optional[FailedCheck] = None + query_events: Optional[list[Event | str]] = None + query: Optional[Query] = None + note: Optional[NoteEvent] = None @property def type(self) -> EventType: @@ -100,8 +100,8 @@ class EpochType(str, Enum): class Epoch(ImplicitDict): - case: TestedCase | None = None - events: list[Event] | None = None + case: Optional[TestedCase] = None + events: Optional[list[Event]] = None @property def type(self) -> EpochType: @@ -163,8 +163,8 @@ class ActionNode(ImplicitDict): name: str node_type: ActionNodeType children: list[ActionNode] - scenario: TestedScenario | None = None - skipped_action: SkippedAction | None = None + scenario: Optional[TestedScenario] = None + skipped_action: Optional[SkippedAction] = None @property def rows(self) -> int: diff --git a/monitoring/uss_qualifier/reports/tested_requirements/data_types.py b/monitoring/uss_qualifier/reports/tested_requirements/data_types.py index ac0c4a9739..c58f608bd9 100644 --- a/monitoring/uss_qualifier/reports/tested_requirements/data_types.py +++ b/monitoring/uss_qualifier/reports/tested_requirements/data_types.py @@ -1,6 +1,6 @@ from enum import Enum -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.uss_qualifier.configurations.configuration import ParticipantID from monitoring.uss_qualifier.requirements.definitions import PackageID @@ -167,8 +167,8 @@ class TestedBreakdown(ImplicitDict): class TestRunInformation(ImplicitDict): test_run_id: str - start_time: str | None = None - end_time: str | None = None + start_time: Optional[str] = None + end_time: Optional[str] = None baseline: str environment: str @@ -206,7 +206,7 @@ class ParticipantVerificationInfo(ImplicitDict): status: ParticipantVerificationStatus """Verification status of participant for the associated requirements set.""" - system_version: str | None = None + system_version: Optional[str] = None """The version of the participant's system that was tested, if this information was acquired during testing.""" @@ -217,6 +217,6 @@ class RequirementsVerificationReport(ImplicitDict): participant_verifications: dict[ParticipantID, ParticipantVerificationInfo] """Information regarding verification of compliance for each participant.""" - artifact_configuration: str | None + artifact_configuration: Optional[str] """Name of the tested requirements artifact configuration from the test run configuration, or "post-hoc" if the artifact configuration generating this verification report is not specified in the test run configuration.""" diff --git a/monitoring/uss_qualifier/reports/validation/definitions.py b/monitoring/uss_qualifier/reports/validation/definitions.py index b3d0e05ae7..8040bbde3f 100644 --- a/monitoring/uss_qualifier/reports/validation/definitions.py +++ b/monitoring/uss_qualifier/reports/validation/definitions.py @@ -1,6 +1,6 @@ from __future__ import annotations -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.monitorlib.dicts import JSONAddress from monitoring.uss_qualifier.common_data_definitions import Severity @@ -11,21 +11,21 @@ class SeverityComparison(ImplicitDict): """Exactly one field must be specified.""" - equal_to: Severity | None - at_least: Severity | None - higher_than: Severity | None - no_higher_than: Severity | None - lower_than: Severity | None + equal_to: Optional[Severity] + at_least: Optional[Severity] + higher_than: Optional[Severity] + no_higher_than: Optional[Severity] + lower_than: Optional[Severity] class NumericComparison(ImplicitDict): """Exactly one field must be specified.""" - equal_to: float | None - at_least: float | None - more_than: float | None - no_more_than: float | None - less_than: float | None + equal_to: Optional[float] + at_least: Optional[float] + more_than: Optional[float] + no_more_than: Optional[float] + less_than: Optional[float] # ===== Applicability ===== @@ -40,7 +40,7 @@ class TestScenarioApplicability(ImplicitDict): class FailedCheckApplicability(ImplicitDict): """FailedCheck test report elements are applicable according to this specification.""" - has_severity: SeverityComparison | None + has_severity: Optional[SeverityComparison] """If specified, only FailedChecks with specified severity are applicable.""" @@ -69,25 +69,25 @@ class ValidationCriterionApplicability(ImplicitDict): Exactly one field must be specified.""" - test_scenarios: TestScenarioApplicability | None + test_scenarios: Optional[TestScenarioApplicability] """Only this kind of TestScenarioReport elements are applicable.""" - failed_checks: FailedCheckApplicability | None + failed_checks: Optional[FailedCheckApplicability] """Only this kind of FailedCheck elements are applicable.""" - skipped_actions: SkippedCheckApplicability | None + skipped_actions: Optional[SkippedCheckApplicability] """Only this kind of SkippedCheckReport elements are applicable.""" - address_is: JSONAddress | None + address_is: Optional[JSONAddress] """Only the element at this JSONAddress in the test report is applicable.""" - does_not_satisfy: ValidationCriterionApplicability | None + does_not_satisfy: Optional[ValidationCriterionApplicability] """Only elements that do not satisfy this criterion are applicable.""" - satisfies_all: AllCriteriaApplicability | None + satisfies_all: Optional[AllCriteriaApplicability] """Only elements which satisfy all these criteria are applicable.""" - satisfies_any: AnyCriteriaApplicability | None + satisfies_any: Optional[AnyCriteriaApplicability] """Elements which satisfy any of these criteria are applicable.""" @@ -97,17 +97,17 @@ class ValidationCriterionApplicability(ImplicitDict): class EachElementCondition(ImplicitDict): """A single applicable element must meet this condition. Exactly one field must be specified.""" - has_severity: SeverityComparison | None + has_severity: Optional[SeverityComparison] """The element must be a FailedCheck that has this specified kind of severity.""" - has_execution_error: bool | None + has_execution_error: Optional[bool] """The element must be a TestScenarioReport that either must have or must not have an execution error.""" class ElementGroupCondition(ImplicitDict): """A group of applicable elements must meet this condition. Exactly one field must be specified.""" - count: NumericComparison | None + count: Optional[NumericComparison] """The number of applicable elements must have this specified kind of count.""" @@ -128,19 +128,19 @@ class AnyPassCondition(ImplicitDict): class PassCondition(ImplicitDict): """Condition for passing validation. Exactly one field must be specified.""" - each_element: EachElementCondition | None + each_element: Optional[EachElementCondition] """Condition applies to each applicable element.""" - elements: ElementGroupCondition | None + elements: Optional[ElementGroupCondition] """Condition applies to the group of applicable elements.""" - does_not_pass: PassCondition | None + does_not_pass: Optional[PassCondition] """Overall condition is met only if this specified condition is not met.""" - all_of: AllPassConditions | None + all_of: Optional[AllPassConditions] """Overall condition is met only if all of these specified conditions are met.""" - any_of: AnyPassCondition | None + any_of: Optional[AnyPassCondition] """Overall condition is met if any of these specified conditions are met.""" diff --git a/monitoring/uss_qualifier/requirements/definitions.py b/monitoring/uss_qualifier/requirements/definitions.py index 3d320de30b..3fc0b41efc 100644 --- a/monitoring/uss_qualifier/requirements/definitions.py +++ b/monitoring/uss_qualifier/requirements/definitions.py @@ -2,7 +2,7 @@ import os -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional class RequirementID(str): @@ -120,14 +120,14 @@ def anchor(self) -> str: class RequirementCollection(ImplicitDict): - requirements: list[RequirementID] | None + requirements: Optional[list[RequirementID]] """This collection includes all of these requirements.""" - requirement_sets: list[RequirementSetID] | None + requirement_sets: Optional[list[RequirementSetID]] """This collection includes all requirements in all of these requirement sets.""" - requirement_collections: list[RequirementCollection] | None + requirement_collections: Optional[list[RequirementCollection]] """This collection includes all of the requirements in all of these requirement collections.""" - exclude: RequirementCollection | None + exclude: Optional[RequirementCollection] """This collection does not include any of these requirements, despite all previous fields.""" diff --git a/monitoring/uss_qualifier/resources/astm/f3548/v21/dss.py b/monitoring/uss_qualifier/resources/astm/f3548/v21/dss.py index 6be1b20a54..f869667993 100644 --- a/monitoring/uss_qualifier/resources/astm/f3548/v21/dss.py +++ b/monitoring/uss_qualifier/resources/astm/f3548/v21/dss.py @@ -6,7 +6,7 @@ from urllib.parse import urlparse import s2sphere -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from uas_standards.astm.f3548.v21.api import ( OPERATIONS, AirspaceConflictResponse, @@ -56,13 +56,13 @@ class DSSInstanceSpecification(ImplicitDict): participant_id: str """ID of the USS responsible for this DSS instance""" - user_participant_ids: list[str] | None + user_participant_ids: Optional[list[str]] """IDs of any participants using this DSS instance, apart from the USS responsible for this DSS instance.""" base_url: str """Base URL for the DSS instance according to the ASTM F3548-21 API""" - supports_ovn_request: bool | None + supports_ovn_request: Optional[bool] """Whether this DSS instance supports the optional extension not part of the original F3548 standard API allowing a USS to request a specific OVN when creating or updating an operational intent.""" def __init__(self, *args, **kwargs): diff --git a/monitoring/uss_qualifier/resources/communications/auth_adapter.py b/monitoring/uss_qualifier/resources/communications/auth_adapter.py index 615db07ca0..31a8c7cfb8 100644 --- a/monitoring/uss_qualifier/resources/communications/auth_adapter.py +++ b/monitoring/uss_qualifier/resources/communications/auth_adapter.py @@ -1,7 +1,7 @@ import os from enum import Enum -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.monitorlib import infrastructure from monitoring.monitorlib.auth import make_auth_adapter @@ -16,10 +16,10 @@ class AuthAdapterSpecification(ImplicitDict): * environment_variable_containing_auth_spec """ - auth_spec: str | None + auth_spec: Optional[str] """Literal representation of auth spec. WARNING: Specifying this directly may cause sensitive information to be included in reports and unprotected configuration files.""" - environment_variable_containing_auth_spec: str | None + environment_variable_containing_auth_spec: Optional[str] """Name of environment variable containing the auth spec. This is the preferred method of providing the auth spec.""" scopes_authorized: list[str] diff --git a/monitoring/uss_qualifier/resources/dev/test_exclusions.py b/monitoring/uss_qualifier/resources/dev/test_exclusions.py index 133f2311ae..799b47c6d6 100644 --- a/monitoring/uss_qualifier/resources/dev/test_exclusions.py +++ b/monitoring/uss_qualifier/resources/dev/test_exclusions.py @@ -1,11 +1,11 @@ -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.uss_qualifier.resources.resource import Resource class TestExclusionsSpecification(ImplicitDict): - allow_private_addresses: bool | None - allow_cleartext_queries: bool | None + allow_private_addresses: Optional[bool] + allow_cleartext_queries: Optional[bool] class TestExclusionsResource(Resource[TestExclusionsSpecification]): diff --git a/monitoring/uss_qualifier/resources/files.py b/monitoring/uss_qualifier/resources/files.py index d8ce545e34..31f3657db3 100644 --- a/monitoring/uss_qualifier/resources/files.py +++ b/monitoring/uss_qualifier/resources/files.py @@ -1,7 +1,7 @@ import hashlib import json -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.uss_qualifier import fileio from monitoring.uss_qualifier.fileio import FileReference @@ -11,7 +11,7 @@ class ExternalFile(ImplicitDict): path: FileReference """Location of the external file.""" - hash_sha512: str | None + hash_sha512: Optional[str] """SHA-512 hash of the external file. If specified, the external file's content will be verified to have this hash or else produce an error. diff --git a/monitoring/uss_qualifier/resources/flight_planning/flight_intent.py b/monitoring/uss_qualifier/resources/flight_planning/flight_intent.py index dc926b47d6..d046730d98 100644 --- a/monitoring/uss_qualifier/resources/flight_planning/flight_intent.py +++ b/monitoring/uss_qualifier/resources/flight_planning/flight_intent.py @@ -2,7 +2,7 @@ import json -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.monitorlib.clients.flight_planning.flight_info_template import ( FlightInfoTemplate, @@ -23,7 +23,7 @@ class DeltaFlightIntent(ImplicitDict): source: FlightIntentID """Base the flight intent for this element of a FlightIntentCollection on the element of the collection identified by this field.""" - mutation: dict | None + mutation: Optional[dict] """For each leaf subfield specified in this object, override the value in the corresponding subfield of the flight intent for this element with the specified value. Consider subfields prefixed with + as leaf subfields.""" @@ -32,10 +32,10 @@ class DeltaFlightIntent(ImplicitDict): class FlightIntentCollectionElement(ImplicitDict): """Definition of a single flight intent within a FlightIntentCollection. Exactly one field must be specified.""" - full: FlightInfoTemplate | None + full: Optional[FlightInfoTemplate] """If specified, the full definition of the flight planning intent.""" - delta: DeltaFlightIntent | None + delta: Optional[DeltaFlightIntent] """If specified, a flight planning intent based on another flight intent, but with some changes.""" @@ -45,7 +45,7 @@ class FlightIntentCollection(ImplicitDict): intents: dict[FlightIntentID, FlightIntentCollectionElement] """Flight planning actions that users want to perform.""" - transformations: list[Transformation] | None + transformations: Optional[list[Transformation]] """Transformations to append to all FlightInfoTemplates.""" def resolve(self) -> dict[FlightIntentID, FlightInfoTemplate]: @@ -107,11 +107,11 @@ def resolve(self) -> dict[FlightIntentID, FlightInfoTemplate]: class FlightIntentsSpecification(ImplicitDict): """Exactly one field must be specified.""" - intent_collection: FlightIntentCollection | None + intent_collection: Optional[FlightIntentCollection] """Full flight intent collection, or a $ref to an external file containing a FlightIntentCollection.""" - file: ExternalFile | None + file: Optional[ExternalFile] """Location of file to load, containing a FlightIntentCollection""" - transformations: list[Transformation] | None + transformations: Optional[list[Transformation]] """Transformations to apply to all flight intents' 4D volumes after resolution (if specified)""" diff --git a/monitoring/uss_qualifier/resources/flight_planning/flight_planner.py b/monitoring/uss_qualifier/resources/flight_planning/flight_planner.py index 896933465e..857ce95bad 100644 --- a/monitoring/uss_qualifier/resources/flight_planning/flight_planner.py +++ b/monitoring/uss_qualifier/resources/flight_planning/flight_planner.py @@ -1,6 +1,6 @@ from urllib.parse import urlparse -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.monitorlib import infrastructure from monitoring.monitorlib.clients.flight_planning.client import FlightPlannerClient @@ -16,13 +16,13 @@ class FlightPlannerConfiguration(ImplicitDict): participant_id: str """ID of the flight planner into which test data can be injected""" - scd_injection_base_url: str | None + scd_injection_base_url: Optional[str] """Base URL for the flight planner's implementation of the interfaces/automated_testing/scd/v1/scd.yaml API""" - v1_base_url: str | None + v1_base_url: Optional[str] """Base URL for the flight planner's implementation of the interfaces/automated_testing/flight_planning/v1/flight_planning.yaml API""" - timeout_seconds: float | None = None + timeout_seconds: Optional[float | None] = None """Number of seconds to allow for requests to this flight planner. If None, use default.""" def __init__(self, *args, **kwargs): diff --git a/monitoring/uss_qualifier/resources/flight_planning/flight_planners.py b/monitoring/uss_qualifier/resources/flight_planning/flight_planners.py index 847c0688f5..e8ffe455a0 100644 --- a/monitoring/uss_qualifier/resources/flight_planning/flight_planners.py +++ b/monitoring/uss_qualifier/resources/flight_planning/flight_planners.py @@ -1,6 +1,6 @@ from collections.abc import Iterable -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from uas_standards.interuss.automated_testing.flight_planning.v1.constants import ( Scope as ScopeFlightPlanning, ) @@ -91,10 +91,10 @@ def make_subset(self, select_indices: Iterable[int]) -> list[FlightPlannerResour class FlightPlannerCombinationSelectorSpecification(ImplicitDict): - must_include: list[ParticipantID] | None + must_include: Optional[list[ParticipantID]] """The set of flight planners which must be included in every combination""" - maximum_roles: dict[ParticipantID, int] | None + maximum_roles: Optional[dict[ParticipantID, int]] """Maximum number of roles a particular participant may fill in any given combination""" diff --git a/monitoring/uss_qualifier/resources/geospatial_info/geospatial_info_providers.py b/monitoring/uss_qualifier/resources/geospatial_info/geospatial_info_providers.py index 343d9d244f..66dbe9e86b 100644 --- a/monitoring/uss_qualifier/resources/geospatial_info/geospatial_info_providers.py +++ b/monitoring/uss_qualifier/resources/geospatial_info/geospatial_info_providers.py @@ -1,6 +1,6 @@ from urllib.parse import urlparse -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from uas_standards.interuss.automated_testing.geospatial_map.v1.constants import ( Scope as ScopeGeospatialMap, ) @@ -19,10 +19,10 @@ class GeospatialInfoProviderConfiguration(ImplicitDict): participant_id: str """ID of the geospatial information provider for which geospatial data can be queried""" - geospatial_map_v1_base_url: str | None + geospatial_map_v1_base_url: Optional[str] """Base URL for the geospatial information provider's implementation of the interfaces/automated_testing/geospatial_map/v1/geospatial_map.yaml API""" - timeout_seconds: float | None = None + timeout_seconds: Optional[float | None] = None """Number of seconds to allow for requests to this geospatial information provider. If None, use default.""" def __init__(self, *args, **kwargs): diff --git a/monitoring/uss_qualifier/resources/interuss/geospatial_map/definitions.py b/monitoring/uss_qualifier/resources/interuss/geospatial_map/definitions.py index 5ecbd834a0..2e504e4810 100644 --- a/monitoring/uss_qualifier/resources/interuss/geospatial_map/definitions.py +++ b/monitoring/uss_qualifier/resources/interuss/geospatial_map/definitions.py @@ -1,6 +1,6 @@ from enum import Enum -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.monitorlib.geotemporal import Volume4DTemplateCollection @@ -26,7 +26,7 @@ class FeatureCheck(ImplicitDict): description: str """Human-readable test step description to aid in the debugging and traceability.""" - operation_rule_set: str | None = None + operation_rule_set: Optional[str] = None """The set of operating rules (or rule set) under which the operation described in the feature check should be performed.""" volumes: Volume4DTemplateCollection @@ -35,7 +35,7 @@ class FeatureCheck(ImplicitDict): A service provider is expected to provide geospatial features relevant to any of the entire area specified and for any of the entire time specified. """ - restriction_source: str | None = None + restriction_source: Optional[str] = None """Which source for geospatial features describing restrictions should be considered when looking for the expected outcome.""" expected_result: ExpectedFeatureCheckResult diff --git a/monitoring/uss_qualifier/resources/interuss/geospatial_map/feature_check_table.py b/monitoring/uss_qualifier/resources/interuss/geospatial_map/feature_check_table.py index 0b2060b513..5d6f22c666 100644 --- a/monitoring/uss_qualifier/resources/interuss/geospatial_map/feature_check_table.py +++ b/monitoring/uss_qualifier/resources/interuss/geospatial_map/feature_check_table.py @@ -3,7 +3,7 @@ import _jsonnet import arrow -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.uss_qualifier.resources.files import ( ExternalFile, @@ -17,14 +17,14 @@ class FeatureCheckTableGenerationSpecification(ImplicitDict): - dict_resources: dict[str, ExternalFile] | None + dict_resources: Optional[dict[str, ExternalFile]] """External dict-like content (.json, .yaml, .jsonnet) to load and make available to the script. Key defines the name of the resource accessible to the script. """ jsonnet_script: ExternalFile """Source of Jsonnet "script" that produces a FeatureCheckTable. - + This converter may access resources with std.extVars("resource_name"). Also, std.extVars("now") returns the current datetime as an ISO string. The return value of the Jsonnet must be an object following the FeatureCheckTable schema. `import` is not allowed. The following additional functions are available: @@ -35,10 +35,10 @@ class FeatureCheckTableGenerationSpecification(ImplicitDict): class FeatureCheckTableSpecification(ImplicitDict): - table: FeatureCheckTable | None + table: Optional[FeatureCheckTable] """Statically-defined feature check table""" - generate_at_runtime: FeatureCheckTableGenerationSpecification | None + generate_at_runtime: Optional[FeatureCheckTableGenerationSpecification] """Generate feature check table at runtime""" diff --git a/monitoring/uss_qualifier/resources/interuss/mock_uss/client.py b/monitoring/uss_qualifier/resources/interuss/mock_uss/client.py index 39d9e88bec..8297e990d9 100644 --- a/monitoring/uss_qualifier/resources/interuss/mock_uss/client.py +++ b/monitoring/uss_qualifier/resources/interuss/mock_uss/client.py @@ -1,4 +1,4 @@ -from implicitdict import ImplicitDict, StringBasedDateTime +from implicitdict import ImplicitDict, Optional, StringBasedDateTime from monitoring.monitorlib import fetch from monitoring.monitorlib.clients.flight_planning.client import FlightPlannerClient @@ -136,7 +136,7 @@ class MockUSSSpecification(ImplicitDict): participant_id: ParticipantID """Test participant responsible for this mock USS.""" - timeout_seconds: float | None = None + timeout_seconds: Optional[float] = None """Number of seconds to allow for requests to this mock_uss instance. If None, use default.""" diff --git a/monitoring/uss_qualifier/resources/interuss/query_behavior.py b/monitoring/uss_qualifier/resources/interuss/query_behavior.py index 0259a5004a..59f24fcb90 100644 --- a/monitoring/uss_qualifier/resources/interuss/query_behavior.py +++ b/monitoring/uss_qualifier/resources/interuss/query_behavior.py @@ -1,4 +1,4 @@ -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from loguru import logger from monitoring.monitorlib.fetch import settings @@ -6,19 +6,19 @@ class QueryBehaviorSpecification(ImplicitDict): - connect_timeout_seconds: float | None + connect_timeout_seconds: Optional[float] """Number of seconds to allow for establishing a connection. Use 0 for no timeout.""" - read_timeout_seconds: float | None + read_timeout_seconds: Optional[float] """Number of seconds to allow for a request to complete after establishing a connection. Use 0 for no timeout.""" - attempts: int | None + attempts: Optional[int] """Number of attempts to query when experiencing a retryable error like a timeout""" - add_request_id: bool | None + add_request_id: Optional[bool] """Whether to automatically add a `request_id` field to any request with a JSON body and no pre-existing `request_id` field""" - fake_netlocs: list[str] | None + fake_netlocs: Optional[list[str]] """Network locations well-known to be fake and for which a request should fail immediately without being attempted.""" diff --git a/monitoring/uss_qualifier/resources/interuss/uss_identification.py b/monitoring/uss_qualifier/resources/interuss/uss_identification.py index 6fb0b82ed6..b6958280e7 100644 --- a/monitoring/uss_qualifier/resources/interuss/uss_identification.py +++ b/monitoring/uss_qualifier/resources/interuss/uss_identification.py @@ -1,6 +1,6 @@ import re -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.monitorlib.fetch import Query from monitoring.uss_qualifier.configurations.configuration import ParticipantID @@ -8,18 +8,18 @@ class AccessTokenIdentifier(ImplicitDict): - issuer: str | None + issuer: Optional[str] """If specified, this identifier only applies to access tokens from this issuer. If not specified, this identifier applies to any access token.""" - subject: str | None + subject: Optional[str] """If specified, assume the participant is responsible for applicable access tokens containing this subject.""" class USSIdentifiers(ImplicitDict): - astm_url_regexes: list[str] | None + astm_url_regexes: Optional[list[str]] """If a URL to an ASTM (F3411, F3548, etc) endpoint matches one of these regular expressions, assume the participant is responsible for that server""" - access_tokens: list[AccessTokenIdentifier] | None + access_tokens: Optional[list[AccessTokenIdentifier]] """If an access token matches one of these identifiers, assume the participant is responsible for that access token""" diff --git a/monitoring/uss_qualifier/resources/netrid/flight_data.py b/monitoring/uss_qualifier/resources/netrid/flight_data.py index 0408374412..6c73f321ae 100644 --- a/monitoring/uss_qualifier/resources/netrid/flight_data.py +++ b/monitoring/uss_qualifier/resources/netrid/flight_data.py @@ -1,4 +1,9 @@ -from implicitdict import ImplicitDict, StringBasedDateTime, StringBasedTimeDelta +from implicitdict import ( + ImplicitDict, + Optional, + StringBasedDateTime, + StringBasedTimeDelta, +) from uas_standards.interuss.automated_testing.rid.v1 import injection from monitoring.uss_qualifier.resources.files import ExternalFile @@ -30,7 +35,7 @@ class AdjacentCircularFlightsSimulatorConfiguration(ImplicitDict): relative to a time close to the time of test. """ - random_seed: int | None = 12345 + random_seed: Optional[int] = 12345 """Pseudorandom seed that should be used, or specify None to use default Random.""" minx: float = 7.4735784530639648 @@ -63,7 +68,7 @@ class FlightDataKMLFileConfiguration(ImplicitDict): relative to a time close to the time of test. """ - random_seed: int | None = 12345 + random_seed: Optional[int] = 12345 """Pseudorandom seed that should be used, or specify None to use default Random.""" kml_file: ExternalFile @@ -74,13 +79,13 @@ class FlightDataSpecification(ImplicitDict): flight_start_delay: StringBasedTimeDelta = StringBasedTimeDelta("15s") """Amount of time between starting the test and commencement of flights""" - record_source: ExternalFile | None + record_source: Optional[ExternalFile] """When this field is populated, flight record data will be loaded directly from this file""" - kml_source: FlightDataKMLFileConfiguration | None + kml_source: Optional[FlightDataKMLFileConfiguration] """When this field is populated, flight data will be generated from a KML file""" - adjacent_circular_flights_simulation_source: ( - AdjacentCircularFlightsSimulatorConfiguration | None - ) + adjacent_circular_flights_simulation_source: Optional[ + AdjacentCircularFlightsSimulatorConfiguration + ] """When this field is populated, flight data will be simulated with the AdjacentCircularFlightsSimulator""" diff --git a/monitoring/uss_qualifier/resources/netrid/flight_data_resources.py b/monitoring/uss_qualifier/resources/netrid/flight_data_resources.py index c68db0dcb9..3e61cbed09 100644 --- a/monitoring/uss_qualifier/resources/netrid/flight_data_resources.py +++ b/monitoring/uss_qualifier/resources/netrid/flight_data_resources.py @@ -5,7 +5,7 @@ from typing import Self import arrow -from implicitdict import ImplicitDict, StringBasedDateTime +from implicitdict import ImplicitDict, Optional, StringBasedDateTime from uas_standards.interuss.automated_testing.rid.v1.injection import ( RIDAircraftState, TestFlightDetails, @@ -221,10 +221,10 @@ def _validate_flight(self, flight): class FlightDataStorageSpecification(ImplicitDict): - flight_record_collection_path: str | None + flight_record_collection_path: Optional[str] """Path, usually ending with .json, at which to store the FlightRecordCollection""" - geojson_tracks_path: str | None + geojson_tracks_path: Optional[str] """Path (folder) in which to store track_XX.geojson files, 1 for each flight""" diff --git a/monitoring/uss_qualifier/resources/planning_area.py b/monitoring/uss_qualifier/resources/planning_area.py index d7de775dec..fd486c0d14 100644 --- a/monitoring/uss_qualifier/resources/planning_area.py +++ b/monitoring/uss_qualifier/resources/planning_area.py @@ -1,6 +1,6 @@ import datetime -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from uas_standards.astm.f3548.v21.api import ( EntityID, EntityOVN, @@ -26,7 +26,7 @@ class PlanningAreaSpecification(ImplicitDict): - The volume itself is declared separately and passed as a dependency: see resource.VolumeResource for details. """ - base_url: str | None + base_url: Optional[str] """Base URL for the USS Note that this is the base URL for the F3548-21 USS API, not the flights or any other specific URL. diff --git a/monitoring/uss_qualifier/resources/versioning/client.py b/monitoring/uss_qualifier/resources/versioning/client.py index b5caea4c71..216b8ece7d 100644 --- a/monitoring/uss_qualifier/resources/versioning/client.py +++ b/monitoring/uss_qualifier/resources/versioning/client.py @@ -1,4 +1,4 @@ -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from uas_standards.interuss.automated_testing.versioning.constants import Scope from monitoring.monitorlib.clients.versioning.client import VersioningClient @@ -18,7 +18,7 @@ class InterUSSVersionProvider(ImplicitDict): class VersionProviderSpecification(ImplicitDict): - interuss: InterUSSVersionProvider | None = None + interuss: Optional[InterUSSVersionProvider] = None """Populated when the version provider is using the InterUSS automated testing versioning API to provide versioning information.""" participant_id: ParticipantID diff --git a/monitoring/uss_qualifier/scenarios/astm/utm/test_steps.py b/monitoring/uss_qualifier/scenarios/astm/utm/test_steps.py index d5eace6db2..dcdd5bf87f 100644 --- a/monitoring/uss_qualifier/scenarios/astm/utm/test_steps.py +++ b/monitoring/uss_qualifier/scenarios/astm/utm/test_steps.py @@ -2,7 +2,7 @@ from enum import Enum -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from uas_standards.astm.f3548.v21.api import ( EntityID, GetOperationalIntentDetailsResponse, @@ -55,7 +55,7 @@ class OpIntentValidator: _after_oi_refs: list[OperationalIntentReference] _after_query: fetch.Query - _new_oi_ref: OperationalIntentReference | None = None + _new_oi_ref: Optional[OperationalIntentReference] = None def __init__( self, @@ -627,10 +627,10 @@ class OpIntentValidationFailureType(str, Enum): class OpIntentValidationFailure(ImplicitDict): validation_failure_type: OpIntentValidationFailureType - error_text: str | None = None + error_text: Optional[str] = None """Any error_text returned after validation check""" - errors: list[schema_validation.ValidationError] | None = None + errors: Optional[list[schema_validation.ValidationError]] = None """Any errors returned after validation check""" def __hash__(self): diff --git a/monitoring/uss_qualifier/scenarios/documentation/definitions.py b/monitoring/uss_qualifier/scenarios/documentation/definitions.py index 799f5bea9c..b40a4ecb1d 100644 --- a/monitoring/uss_qualifier/scenarios/documentation/definitions.py +++ b/monitoring/uss_qualifier/scenarios/documentation/definitions.py @@ -1,4 +1,4 @@ -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.uss_qualifier.common_data_definitions import Severity from monitoring.uss_qualifier.reports.report import RequirementID @@ -6,21 +6,21 @@ class TestCheckDocumentation(ImplicitDict): name: str - url: str | None = None + url: Optional[str] = None applicable_requirements: list[RequirementID] has_todo: bool - severity: Severity | None = None + severity: Optional[Severity] = None class TestStepDocumentation(ImplicitDict): name: str - url: str | None = None + url: Optional[str] = None checks: list[TestCheckDocumentation] class TestCaseDocumentation(ImplicitDict): name: str - url: str | None = None + url: Optional[str] = None steps: list[TestStepDocumentation] def get_step_by_name(self, step_name: str) -> TestStepDocumentation | None: @@ -32,11 +32,11 @@ def get_step_by_name(self, step_name: str) -> TestStepDocumentation | None: class TestScenarioDocumentation(ImplicitDict): name: str - url: str | None = None + url: Optional[str] = None local_path: str - resources: list[str] | None + resources: Optional[list[str]] cases: list[TestCaseDocumentation] - cleanup: TestStepDocumentation | None + cleanup: Optional[TestStepDocumentation] def get_case_by_name(self, case_name: str) -> TestCaseDocumentation | None: for case in self.cases: diff --git a/monitoring/uss_qualifier/suites/definitions.py b/monitoring/uss_qualifier/suites/definitions.py index 1ba3caddbd..ca5a94c00b 100644 --- a/monitoring/uss_qualifier/suites/definitions.py +++ b/monitoring/uss_qualifier/suites/definitions.py @@ -2,7 +2,7 @@ from enum import Enum -from implicitdict import ImplicitDict +from implicitdict import ImplicitDict, Optional from monitoring.uss_qualifier.action_generators.definitions import ( ActionGeneratorDefinition, @@ -22,13 +22,13 @@ class TestSuiteDeclaration(ImplicitDict): - suite_type: TestSuiteTypeName | None + suite_type: Optional[TestSuiteTypeName] """Type/location of test suite. Usually expressed as the file name of the suite definition (without extension) qualified relative to the `uss_qualifier` folder""" - suite_definition: TestSuiteDefinition | None + suite_definition: Optional[TestSuiteDefinition] """Definition of test suite internal to the configuration -- specified instead of `suite_type`.""" - resources: dict[ResourceID, ResourceID] | None + resources: Optional[dict[ResourceID, ResourceID]] """Mapping of the ID a resource will be known by in the child test suite -> the ID a resource is known by in the parent test suite. The child suite resource is supplied by the parent suite resource . @@ -86,13 +86,13 @@ class TestSuiteActionDeclaration(ImplicitDict): Exactly one of `test_scenario`, `test_suite`, or `action_generator` must be specified. """ - test_scenario: TestScenarioDeclaration | None + test_scenario: Optional[TestScenarioDeclaration] """If this field is populated, declaration of the test scenario to run""" - test_suite: TestSuiteDeclaration | None + test_suite: Optional[TestSuiteDeclaration] """If this field is populated, declaration of the test suite to run""" - action_generator: ActionGeneratorDefinition | None + action_generator: Optional[ActionGeneratorDefinition] """If this field is populated, declaration of a generator that will produce 0 or more test suite actions""" on_failure: ReactionToFailure = ReactionToFailure.Continue @@ -140,13 +140,13 @@ class TestSuiteDefinition(ImplicitDict): resources: dict[ResourceID, ResourceTypeNameSpecifyingOptional] """Enumeration of the resources used by this test suite""" - local_resources: dict[ResourceID, ResourceDeclaration] | None + local_resources: Optional[dict[ResourceID, ResourceDeclaration]] """Declarations of resources originating in this test suite. If a resource is defined in both `resources` and `local_resources`, the resource in `local_resources` will be ignored (`resources` overrides `local_resources`).""" actions: list[TestSuiteActionDeclaration] """The actions to take when running the test suite. Components will be executed in order.""" - participant_verifiable_capabilities: list[ParticipantCapabilityDefinition] | None + participant_verifiable_capabilities: Optional[list[ParticipantCapabilityDefinition]] """Definitions of capabilities verified by this test suite for individual participants.""" @staticmethod