From 4a7f1a76c70b68d4e3190465c5204c057fc9db4b Mon Sep 17 00:00:00 2001 From: Matt Johnson Date: Fri, 15 May 2026 21:47:06 +0000 Subject: [PATCH] =?UTF-8?q?refactor:=20rename=20CloudEvents=20extension=20?= =?UTF-8?q?attributes=20hub*=20=E2=86=92=20central*?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename extension attributes for consistency with project naming: - hubschemaversion → centralschemaversion - hubcategory → centralcategory - hubseverity → centralseverity Non-breaking change - no consumers depend on these names yet. Co-Authored-By: Claude Opus 4.5 --- src/central/cloudevents_wire.py | 22 ++++++++--------- tests/test_models.py | 44 ++++++++++++++++----------------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/central/cloudevents_wire.py b/src/central/cloudevents_wire.py index b8507fb..fcd388a 100644 --- a/src/central/cloudevents_wire.py +++ b/src/central/cloudevents_wire.py @@ -11,27 +11,27 @@ from central.models import Event def wrap_event(event: Event, config: Config) -> tuple[dict[str, Any], str]: """ Wrap an Event into a CNCF CloudEvents v1.0 JSON envelope. - + Returns: A tuple of (envelope_dict, msg_id) where msg_id is the CloudEvent id for use as Nats-Msg-Id header. """ # Build CE type: {prefix}.{category}.v1 ce_type = f"{config.cloudevents.type_prefix}.{event.category}.v1" - + # Serialize event data event_data = event.model_dump(mode="json") - + # Build extension attributes - lowercase, no underscores per CE spec extensions: dict[str, Any] = { - "hubschemaversion": config.cloudevents.schema_version, - "hubcategory": event.category, + "centralschemaversion": config.cloudevents.schema_version, + "centralcategory": event.category, } - - # Only include hubseverity if severity is present + + # Only include centralseverity if severity is present if event.severity is not None: - extensions["hubseverity"] = event.severity - + extensions["centralseverity"] = event.severity + # Create CloudEvent ce = CloudEvent( attributes={ @@ -44,9 +44,9 @@ def wrap_event(event: Event, config: Config) -> tuple[dict[str, Any], str]: }, data=event_data, ) - + # Build envelope dict from CloudEvent envelope: dict[str, Any] = dict(ce.get_attributes()) envelope["data"] = ce.data - + return envelope, event.id diff --git a/tests/test_models.py b/tests/test_models.py index 3999f85..f9a0289 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -59,12 +59,12 @@ def sample_config() -> Config: class TestSubjectForEvent: """Tests for subject_for_event helper.""" - + def test_county_subject(self, sample_event: Event) -> None: """County codes produce county subject.""" subject = subject_for_event(sample_event) assert subject == "central.wx.alert.us.id.county.ada" - + def test_zone_subject(self, sample_geo: Geo) -> None: """Zone codes produce zone subject.""" geo = Geo( @@ -83,7 +83,7 @@ class TestSubjectForEvent: ) subject = subject_for_event(event) assert subject == "central.wx.alert.us.id.zone.z033" - + def test_unknown_subject(self, sample_event: Event) -> None: """Missing primary_region produces unknown subject.""" geo = Geo(regions=[], primary_region=None) @@ -97,7 +97,7 @@ class TestSubjectForEvent: ) subject = subject_for_event(event) assert subject == "central.wx.alert.us.unknown" - + def test_custom_prefix(self, sample_event: Event) -> None: """Custom prefix is used in subject.""" subject = subject_for_event(sample_event, prefix="myapp.events") @@ -106,13 +106,13 @@ class TestSubjectForEvent: class TestCloudEventsWire: """Tests for CloudEvents wire format.""" - + def test_required_fields_present( self, sample_event: Event, sample_config: Config ) -> None: """Required CloudEvents fields are present.""" envelope, msg_id = wrap_event(sample_event, sample_config) - + assert msg_id == sample_event.id assert envelope["id"] == sample_event.id assert envelope["source"] == sample_config.cloudevents.source @@ -121,27 +121,27 @@ class TestCloudEventsWire: assert "time" in envelope assert envelope["datacontenttype"] == "application/json" assert "data" in envelope - + def test_extension_attributes_lowercase( self, sample_event: Event, sample_config: Config ) -> None: """Extension attributes are lowercase with no underscores.""" envelope, _ = wrap_event(sample_event, sample_config) - + # Check that extension attributes exist and are lowercase - assert envelope["hubschemaversion"] == "1.0" - assert envelope["hubcategory"] == "wx.alert.severe_thunderstorm_warning" - assert envelope["hubseverity"] == 3 - + assert envelope["centralschemaversion"] == "1.0" + assert envelope["centralcategory"] == "wx.alert.severe_thunderstorm_warning" + assert envelope["centralseverity"] == 3 + # Verify no uppercase or underscores in extension names - for key in ["hubschemaversion", "hubcategory", "hubseverity"]: + for key in ["centralschemaversion", "centralcategory", "centralseverity"]: assert key.islower() assert "_" not in key - - def test_severity_none_omits_hubseverity( + + def test_severity_none_omits_centralseverity( self, sample_geo: Geo, sample_config: Config ) -> None: - """When severity is None, hubseverity is omitted entirely.""" + """When severity is None, centralseverity is omitted entirely.""" event = Event( id="test-no-severity", source="test", @@ -151,11 +151,11 @@ class TestCloudEventsWire: geo=sample_geo, data={}, ) - + envelope, _ = wrap_event(event, sample_config) - - # hubseverity should not be present at all - assert "hubseverity" not in envelope + + # centralseverity should not be present at all + assert "centralseverity" not in envelope # Other extensions should still be present - assert "hubschemaversion" in envelope - assert "hubcategory" in envelope + assert "centralschemaversion" in envelope + assert "centralcategory" in envelope