Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 0 additions & 72 deletions .basedpyright/baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -11931,14 +11931,6 @@
}
],
"./monitoring/uss_qualifier/scenarios/astm/netrid/display_data_evaluator.py": [
{
"code": "reportAttributeAccessIssue",
"range": {
"startColumn": 30,
"endColumn": 33,
"lineCount": 1
}
},
{
"code": "reportOptionalSubscript",
"range": {
Expand Down Expand Up @@ -12091,14 +12083,6 @@
"lineCount": 1
}
},
{
"code": "reportArgumentType",
"range": {
"startColumn": 16,
"endColumn": 39,
"lineCount": 1
}
},
{
"code": "reportOperatorIssue",
"range": {
Expand Down Expand Up @@ -12309,14 +12293,6 @@
"lineCount": 1
}
},
{
"code": "reportArgumentType",
"range": {
"startColumn": 12,
"endColumn": 13,
"lineCount": 1
}
},
{
"code": "reportArgumentType",
"range": {
Expand All @@ -12325,14 +12301,6 @@
"lineCount": 1
}
},
{
"code": "reportArgumentType",
"range": {
"startColumn": 28,
"endColumn": 29,
"lineCount": 1
}
},
{
"code": "reportAttributeAccessIssue",
"range": {
Expand Down Expand Up @@ -13723,30 +13691,6 @@
"lineCount": 1
}
},
{
"code": "reportAttributeAccessIssue",
"range": {
"startColumn": 92,
"endColumn": 101,
"lineCount": 1
}
},
{
"code": "reportReturnType",
"range": {
"startColumn": 19,
"endColumn": 23,
"lineCount": 1
}
},
{
"code": "reportReturnType",
"range": {
"startColumn": 15,
"endColumn": 52,
"lineCount": 1
}
},
{
"code": "reportInvalidTypeVarUse",
"range": {
Expand Down Expand Up @@ -15560,22 +15504,6 @@
"endColumn": 82,
"lineCount": 1
}
},
{
"code": "reportOptionalMemberAccess",
"range": {
"startColumn": 40,
"endColumn": 48,
"lineCount": 1
}
},
{
"code": "reportOptionalMemberAccess",
"range": {
"startColumn": 74,
"endColumn": 81,
"lineCount": 1
}
}
],
"./monitoring/uss_qualifier/scenarios/astm/utm/dss/synchronization/constraint_ref_synchronization.py": [
Expand Down
3 changes: 2 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ This document contains key context, nuances, and troubleshooting tips specifical

## 2. Navigating Data Schemas
- **Implicit Types**: Many schema objects inherit from `ImplicitDict`. This means that reading their raw Python class definitions may not reveal all their expected structure. Rely on their `__annotations__` or their OpenAPI documentation.
- **Optional `ImplicitDict` Fields**: `ImplicitDict` fields annotated with `| None` (or `Optional[...]`) indicate optional dictionary keys. When constructing an `ImplicitDict` instance, omit optional fields that do not have a value rather than explicitly passing `None` (which would insert a `null` value into the serialized dictionary).
- **Optional `ImplicitDict` Fields**: `ImplicitDict` fields annotated with `| None` (or `Optional[...]`) indicate optional dictionary keys. In implicitdict 5.0.0, accessing a missing optional attribute returns `None` without inserting a key; use `"field" in obj` to distinguish absence from an explicitly stored null. Constructor keyword arguments set to `None` normally omit optional values, but class defaults may still populate the key; assigning `obj.field = None` or `obj["field"] = None` stores an explicit null. Use dictionary membership rather than `hasattr` when key presence matters.
- **implicitdict 5.0.0 Typing**: Its unannotated `__getattribute__` introduces `None` into the inferred type of undeclared attributes (`Unknown | Any | None` in basedpyright 1.40.1), while declared fields and properties retain their types. New optional-access diagnostics may expose a nonexistent member or the wrong schema class rather than a missing optional value. Check the receiver's declaration before adding a None guard or suppressing the diagnostic. An explicit `-> Any` return annotation on the accessor restores the previous permissive fallback without changing runtime behavior, but also hides these pre-existing member-access mistakes.
- **Hidden Schema Nuances**: Certain F3548 properties intuitively behave differently than standard logic might predict (e.g., F3548's `OperationalIntentReference` does *not* represent 4D `altitude` extents, whereas `Volume4D` details do). Always verify property existence programmatically instead of relying on assumptions.
- **Datetime Types**: Fields annotated as `StringBasedDateTime` (or generic `Time` structures wrapping it) inherently expose a `.datetime` property mapping directly to Python's built-in `datetime.datetime` type. Always rely on this `.datetime` attribute for date-math instead of manually parsing string strings.
- **DSS Base URL Suffixes**: When configuring DSS instances, the base URL for ASTM F3411-22a (NetRID v2) requires the `/rid/v2` suffix path (e.g. `http://dss1.uss1.localutm/rid/v2`), whereas F3411-19 and SCD (F3548) typically use the host base URL directly without that suffix.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,9 @@ class PotentialGeneratedAction(ImplicitDict):
test_scenario: Optional[PotentialTestScenarioAction]
test_suite: Optional[PotentialTestSuiteAction]
action_generator: Optional[PotentialActionGeneratorAction]

@property
def invalid_type_error(self) -> ValueError:
return ValueError(
"Invalid PotentialGeneratedAction: test_scenario, test_suite or action_generator must be specified"
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import pytest

from monitoring.uss_qualifier.action_generators.documentation.definitions import (
PotentialGeneratedAction,
)
from monitoring.uss_qualifier.reports.tested_requirements.breakdown import (
_populate_breakdown_with_action_declaration,
)
from monitoring.uss_qualifier.reports.tested_requirements.data_types import (
TestedBreakdown as Breakdown,
)
from monitoring.uss_qualifier.suites.documentation.documentation import (
TestSuiteRenderContext as RenderContext,
)
from monitoring.uss_qualifier.suites.documentation.documentation import (
_collect_requirements_from_action,
_render_action,
)


@pytest.mark.parametrize("consumer", ["render", "requirements", "breakdown"])
# This test is AI-generated and has not been closely inspected by a human.
def test_invalid_generated_action_reports_value_error(consumer: str):
action = PotentialGeneratedAction()
with pytest.raises(ValueError, match="Invalid PotentialGeneratedAction"):
if consumer == "render":
_render_action(
action,
RenderContext("suite.yaml", "suite.md", ".", 0, 0, {}),
)
elif consumer == "requirements":
_collect_requirements_from_action(action)
else:
_populate_breakdown_with_action_declaration(
Breakdown(packages=[]), action, [], None
)
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ def _search_earliest_incl_step():
check.record_failed(
f"ISAs search did not return expected ISA {self._isa_id}",
details=f"Search in area {self._isa_area} from time {earliest} returned ISAs {isas.isas.keys()}",
query_timestamps=[isas.dss_query.query.request.timestamp],
query_timestamps=[isas.query.request.timestamp],
)
else:
isa_validator = ISAValidator(
Expand Down Expand Up @@ -272,7 +272,7 @@ def _search_earliest_excl_step():
check.record_failed(
f"ISAs search returned unexpected ISA {self._isa_id}",
details=f"Search in area {self._isa_area} from time {earliest} returned ISAs {isas.isas.keys()}",
query_timestamps=[isas.dss_query.query.request.timestamp],
query_timestamps=[isas.query.request.timestamp],
)

self.end_test_step()
Expand All @@ -299,7 +299,7 @@ def _search_latest_incl_step():
check.record_failed(
f"ISAs search did not return expected ISA {self._isa_id}",
details=f"Search in area {self._isa_area} to time {latest} returned ISAs {isas.isas.keys()}",
query_timestamps=[isas.dss_query.query.request.timestamp],
query_timestamps=[isas.query.request.timestamp],
)
else:
isa_validator = ISAValidator(
Expand Down Expand Up @@ -338,7 +338,7 @@ def _search_latest_excl_step():
check.record_failed(
f"ISAs search returned unexpected ISA {self._isa_id}",
details=f"Search in area {self._isa_area} to time {latest} returned ISAs {isas.isas.keys()}",
query_timestamps=[isas.dss_query.query.request.timestamp],
query_timestamps=[isas.query.request.timestamp],
)

self.end_test_step()
Expand All @@ -363,7 +363,7 @@ def _search_area_only_step():
check.record_failed(
f"ISAs search did not return expected ISA {self._isa_id}",
details=f"Search in area {self._isa_area} returned ISAs {isas.isas.keys()}",
query_timestamps=[isas.dss_query.query.request.timestamp],
query_timestamps=[isas.query.request.timestamp],
)
else:
isa_validator = ISAValidator(
Expand Down Expand Up @@ -530,7 +530,7 @@ def _search_isa_step():
check.record_failed(
f"ISAs search returned deleted ISA {self._isa_id}",
details=f"Search in area {self._isa_area} returned ISAs {isas.isas.keys()}",
query_timestamps=[isas.dss_query.query.request.timestamp],
query_timestamps=[isas.query.request.timestamp],
)

self.end_test_step()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
injection,
)
from monitoring.uss_qualifier.scenarios.astm.netrid.display_data_evaluator import (
DPObservedFlight,
FetchedToInjectedCache,
TelemetryMapping,
)
Expand Down Expand Up @@ -167,7 +168,9 @@ def poll_func(rect: LatLngRect) -> bool:
def _is_area_too_large(self, rect: s2sphere.LatLngRect) -> bool:
return geo.get_latlngrect_diagonal_km(rect) > self._rid_version.max_diagonal_km

def _fetch_flights_from_dss(self, rect: LatLngRect) -> dict[str, TelemetryMapping]:
def _fetch_flights_from_dss(
self, rect: LatLngRect
) -> dict[str, TelemetryMapping[DPObservedFlight]]:
# We grab all flights from the SPs (which we know how to reach by first querying the DSS).
# This is authenticated and is expected to succeed
sp_observation = rid.all_flights(
Expand Down Expand Up @@ -215,7 +218,10 @@ def _evaluate_and_test_too_large_area_requests(
return set(mapping_by_injection_id.keys())

def _evaluate_too_large_area(
self, rect: LatLngRect, injection_id: str, mapping: TelemetryMapping
self,
rect: LatLngRect,
injection_id: str,
mapping: TelemetryMapping[DPObservedFlight],
):
participant_id = mapping.injected_flight.uss_participant_id
flights_url = mapping.observed_flight.query.flights_url
Expand Down
Loading
Loading