-
Notifications
You must be signed in to change notification settings - Fork 32
feat: Add Notification Client #195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
37 commits
Select commit
Hold shift + click to select a range
1b68230
feat: Add models for Notification Strategy API
IN2026-Rohith-Raja fdb58a3
feat: Add Client for Notification API
IN2026-Rohith-Raja 3796ff1
test: Add tests for Notification CLient API
IN2026-Rohith-Raja d1d8dc6
docs: Add notification.rst in docs
IN2026-Rohith-Raja 2d0fd9e
feat: Add example for notification client
IN2026-Rohith-Raja 9569daf
refactor: Changes in docstrings, included TypedDict for required fields
IN2026-Rohith-Raja 63437c7
refactor: Minor lint changes, used enum for required fields
IN2026-Rohith-Raja 2a31691
refactor: Refactored model to handle nullable fields
IN2026-Rohith-Raja 035457d
docs: Change in config docs
IN2026-Rohith-Raja 2aa9201
docs: Updated getting_started.rst
IN2026-Rohith-Raja 74e2713
refactor: Refactored changes mentioned
IN2026-Rohith-Raja 5cc4edf
refactor: Refactored models used in test
IN2026-Rohith-Raja 5c42127
refactor: Updated example
IN2026-Rohith-Raja be56bb9
refactor: Updated example
IN2026-Rohith-Raja dd6f99f
refactor: Change config
IN2026-Rohith-Raja cfe160f
Merge branch 'notification-client' of https://github.com/IN2026-Rohit…
IN2026-Rohith-Raja 1bb60f6
refactor: Minor refactors
IN2026-Rohith-Raja 29608ab
Merge branch 'master'
IN2026-Rohith-Raja 1d4bf65
feat: Add Notification Client
IN2026-Rohith-Raja a77b3a5
refactor: File name changed
IN2026-Rohith-Raja 78fe479
refactor: File name change
IN2026-Rohith-Raja 61c4358
refactor: Change in model file name
IN2026-Rohith-Raja dbcdfab
refactor: Change in config structure
IN2026-Rohith-Raja 6150b65
Merge branch 'master' into notification-client
IN2026-Rohith-Raja 9a58956
refactor: Change in config structure
IN2026-Rohith-Raja 76ff904
Merge branch 'notification-client' of https://github.com/IN2026-Rohit…
IN2026-Rohith-Raja 0b44d48
refactor: Change in model structure
IN2026-Rohith-Raja 4ea0288
fix: Import error in pipeline
IN2026-Rohith-Raja 4e71b5a
fix: Type annotation issue
IN2026-Rohith-Raja b6ceec4
refactor: Minor changes including change in function name
IN2026-Rohith-Raja 9b29bb5
fix: Faked http calls for test
IN2026-Rohith-Raja 109fcb5
refactor: Linting issue
IN2026-Rohith-Raja e3114e0
refactor: Change in docstring and variable names
IN2026-Rohith-Raja 4554a1a
refactor: Change in test names
IN2026-Rohith-Raja 6ae0342
tests: Include cases to test configuration validator
IN2026-Rohith-Raja 4b6b28e
refactor: Included model validator to set service name on smtp models
IN2026-Rohith-Raja cb1321c
refactor: Linting
IN2026-Rohith-Raja File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| .. _api_notification_page: | ||
|
|
||
| nisystemlink.clients.notification | ||
| ========================== | ||
|
|
||
| .. autoclass:: nisystemlink.clients.notification.NotificationClient | ||
| :exclude-members: __init__ | ||
|
|
||
| .. automethod:: __init__ | ||
| .. automethod:: apply_dynamic_notification_strategy | ||
|
|
||
| .. automodule:: nisystemlink.clients.notification.models | ||
| :members: | ||
| :imported-members: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| import uuid | ||
| from datetime import datetime | ||
|
|
||
| from nisystemlink.clients.alarm import AlarmClient | ||
| from nisystemlink.clients.alarm.models._alarm import Alarm, AlarmSeverityLevel | ||
| from nisystemlink.clients.alarm.models._create_or_update_alarm_request import ( | ||
| CreateOrUpdateAlarmRequest, | ||
| SetAlarmTransition, | ||
| ) | ||
| from nisystemlink.clients.core import HttpConfiguration | ||
| from nisystemlink.clients.notification import NotificationClient | ||
| from nisystemlink.clients.notification.models import ( | ||
| DynamicNotificationConfiguration, | ||
| DynamicNotificationStrategy, | ||
| DynamicStrategyRequest, | ||
| SmtpAddressFields, | ||
| SmtpAddressGroup, | ||
| SmtpMessageTemplate, | ||
| SmtpMessageTemplateFields, | ||
| ) | ||
|
|
||
| # Server configuration is not required when used with SystemLink Client or run through Jupyter on SystemLink | ||
| server_configuration: HttpConfiguration | None = None | ||
|
|
||
| # To set up the server configuration to point to your instance of SystemLink Enterprise, uncomment | ||
| # the following lines and provide your server URI and API key. | ||
| # server_configuration = HttpConfiguration( | ||
| # server_uri="https://yourserver.yourcompany.com", | ||
| # api_key="", | ||
| # ) | ||
|
|
||
|
|
||
| # Create request for applying strategy | ||
| def create_notification_request_for_alarm( | ||
| alarm: Alarm, | ||
| address_group: SmtpAddressGroup, | ||
| message_template: SmtpMessageTemplate, | ||
| ) -> DynamicStrategyRequest: | ||
| """Creates and returns a dynamic strategy request.""" | ||
| occurred_at = alarm.most_recent_transition_occurred_at | ||
|
|
||
| return DynamicStrategyRequest( | ||
| message_template_substitution_fields={ | ||
| "alarm_id": alarm.alarm_id, | ||
| "alarm_condition": alarm.condition, | ||
| "alarm_description": alarm.description, | ||
| "alarm_severity": str(alarm.current_severity_level), | ||
| "alarm_occurred_at": occurred_at.isoformat() if occurred_at else "", | ||
| }, | ||
| notification_strategy=DynamicNotificationStrategy( | ||
| notification_configurations=[ | ||
| DynamicNotificationConfiguration( | ||
| address_group=address_group, | ||
| message_template=message_template, | ||
| ) | ||
| ] | ||
| ), | ||
| ) | ||
|
|
||
|
|
||
| # Create clients for Notification and Alarm services | ||
| notification_client = NotificationClient(configuration=server_configuration) | ||
| alarm_client = AlarmClient(configuration=server_configuration) | ||
|
|
||
| # Create a unique alarm ID for this example | ||
| alarm_id = f"example_alarm_{uuid.uuid1().hex}" | ||
|
|
||
| # Create an alarm with a SET transition | ||
| create_alarm_request = CreateOrUpdateAlarmRequest( | ||
| alarm_id=alarm_id, | ||
| transition=SetAlarmTransition( | ||
| occurred_at=datetime.now(), | ||
| severity_level=AlarmSeverityLevel.HIGH, | ||
| value="85", | ||
| condition="Greater than 80", | ||
| short_text="Temperature is high", | ||
| detail_text="Temperature sensor reading is 85°C (higher than the configured threshold of 80°C)", | ||
| ), | ||
| description="Example alarm for notification", | ||
| ) | ||
| id = alarm_client.create_or_update_alarm(create_alarm_request) | ||
| print("Alarm created successfully") | ||
|
|
||
| # Get the alarm by its instance ID (the unique occurrence identifier) | ||
| retrieved_alarm = alarm_client.get_alarm(instance_id=id) | ||
|
|
||
| # Define recipients to notify | ||
| recipients = SmtpAddressFields(toAddresses=["sample1@example.com"]) | ||
|
|
||
| # Create address group | ||
| address_group = SmtpAddressGroup( | ||
| display_name="Alarm Notification Recipients", | ||
| properties={"address group": "Alarm"}, | ||
| fields=recipients, | ||
| ) | ||
|
|
||
| # Create mail template for alarm creation notification | ||
| alarm_creation_template = SmtpMessageTemplate( | ||
| display_name="Alarm Creation Template", | ||
| fields=SmtpMessageTemplateFields( | ||
| subject_template="Alarm Created: <alarm_id>", | ||
| body_template="An alarm with ID <alarm_id> has been created.\n" | ||
| "Condition: <alarm_condition>\n" | ||
| "Description: <alarm_description>\n" | ||
| "Current severity: <alarm_severity>\n" | ||
| "Occurred At: <alarm_occurred_at>", | ||
| ), | ||
| ) | ||
|
|
||
| # Send notification for alarm creation | ||
| notification_for_alarm_creation = create_notification_request_for_alarm( | ||
| alarm=retrieved_alarm, | ||
| address_group=address_group, | ||
| message_template=alarm_creation_template, | ||
| ) | ||
| notification_client.apply_dynamic_notification_strategy( | ||
| request=notification_for_alarm_creation | ||
| ) | ||
| print("Notification sent for alarm creation") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| from ._notification_client import NotificationClient | ||
|
|
||
| # flake8: noqa |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| """Implementation of Notification Client""" | ||
|
|
||
| from nisystemlink.clients import core | ||
| from nisystemlink.clients.core._uplink._base_client import BaseClient | ||
| from nisystemlink.clients.core._uplink._methods import post | ||
| from uplink import retry | ||
|
|
||
| from . import models | ||
|
|
||
|
|
||
| @retry( | ||
| when=retry.when.status(408, 429, 502, 503, 504), | ||
| stop=retry.stop.after_attempt(1), | ||
| on_exception=retry.CONNECTION_ERROR, | ||
| ) | ||
| class NotificationClient(BaseClient): | ||
| def __init__(self, configuration: core.HttpConfiguration | None = None): | ||
| """Initialize an instance. | ||
|
|
||
| Args: | ||
| configuration: Defines the web server to connect to and information about | ||
| how to connect. If not provided, the | ||
| :class:`HttpConfigurationManager <nisystemlink.clients.core.HttpConfigurationManager>` | ||
| is used to obtain the configuration. | ||
|
|
||
| Raises: | ||
| ApiException: if unable to communicate with the `/ninotification` service. | ||
| """ | ||
| if configuration is None: | ||
| configuration = core.HttpConfigurationManager.get_configuration() | ||
|
|
||
| super().__init__(configuration, base_path="/ninotification/v1/") | ||
|
|
||
| @post("apply-dynamic-strategy") | ||
| def apply_dynamic_notification_strategy( | ||
| self, request: models.DynamicStrategyRequest | ||
| ) -> None: | ||
| """Applies the notification strategy from the given request. | ||
|
|
||
| Args: | ||
| request: Request with message template substitution fields and notification strategies. | ||
|
|
||
| Returns: | ||
| None. | ||
|
|
||
| Raises: | ||
| ApiException: if unable to communicate with the `/ninotification` service or provided invalid arguments. | ||
| """ | ||
| ... |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| from ._address_group import AddressGroup | ||
| from ._dynamic_strategy_request import DynamicStrategyRequest | ||
| from ._message_template import MessageTemplate | ||
| from ._dynamic_notification_configuration import DynamicNotificationConfiguration | ||
| from ._dynamic_notification_strategy import DynamicNotificationStrategy | ||
| from ._smtp_address_group import SmtpAddressFields, SmtpAddressGroup | ||
| from ._smtp_message_template import SmtpMessageTemplateFields, SmtpMessageTemplate | ||
|
|
||
| # flake8: noqa |
13 changes: 13 additions & 0 deletions
13
nisystemlink/clients/notification/models/_address_group.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| from typing import Dict, List | ||
|
|
||
| from ._base_notification_metadata import BaseNotificationMetadata | ||
|
|
||
|
|
||
| class AddressGroup(BaseNotificationMetadata): | ||
| """Model defining notification recipients for generic service.""" | ||
|
|
||
| interpreting_service_name: str | ||
| """Name of the interpreting service.""" | ||
|
|
||
| fields: Dict[str, List[str]] | ||
| """Address group's fields. Requires at least one valid recipient.""" | ||
23 changes: 23 additions & 0 deletions
23
nisystemlink/clients/notification/models/_base_notification_metadata.py
|
IN2026-Rohith-Raja marked this conversation as resolved.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| from typing import Dict, List | ||
|
|
||
| from nisystemlink.clients.core._uplink._json_model import JsonModel | ||
|
|
||
|
|
||
| class BaseNotificationMetadata(JsonModel): | ||
| id: str | None = None | ||
| """Identifier of the notification metadata""" | ||
|
|
||
| display_name: str | None = None | ||
| """Display name of the object. | ||
|
|
||
| Example: "name" | ||
| """ | ||
|
|
||
| properties: Dict[str, str] | None = None | ||
| """Additional properties for the base metadata. | ||
|
|
||
| Example: { "property": "value" } | ||
| """ | ||
|
|
||
| referencing_notification_strategies: List[str] | None = None | ||
| """List of notification strategies referencing the notification metadata""" |
48 changes: 48 additions & 0 deletions
48
nisystemlink/clients/notification/models/_dynamic_notification_configuration.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| from __future__ import annotations | ||
|
|
||
| from nisystemlink.clients.core._uplink._json_model import JsonModel | ||
| from nisystemlink.clients.notification.models._address_group import AddressGroup | ||
| from nisystemlink.clients.notification.models._message_template import MessageTemplate | ||
| from nisystemlink.clients.notification.models._smtp_address_group import ( | ||
| SmtpAddressGroup, | ||
| ) | ||
| from nisystemlink.clients.notification.models._smtp_message_template import ( | ||
| SmtpMessageTemplate, | ||
| ) | ||
| from pydantic import Field, model_validator | ||
|
|
||
|
|
||
| class DynamicNotificationConfiguration(JsonModel): | ||
| """Model for notification configuration defining address groups and message template for the notification. | ||
|
|
||
| Requires at least one of addressGroupId or addressGroup, and one of messageTemplateId or messageTemplate. | ||
|
rbell517 marked this conversation as resolved.
|
||
| """ | ||
|
|
||
| address_group_id: str | None = None | ||
| """ID referencing the associated address group.""" | ||
|
|
||
| message_template_id: str | None = None | ||
| """ID referencing the associated message template.""" | ||
|
|
||
| address_group: AddressGroup | SmtpAddressGroup | None = Field(default=None) | ||
| """Address group defining notification recipients.""" | ||
|
|
||
| message_template: MessageTemplate | SmtpMessageTemplate | None = Field(default=None) | ||
| """Message template defining notification content structure""" | ||
|
|
||
| @model_validator(mode="after") | ||
| def validate_required_pairs(self) -> DynamicNotificationConfiguration: | ||
| """Validator to check at least one of address_group_id or address_group, and | ||
| one of message_template_id or message_template is present. | ||
| """ | ||
| if self.address_group_id is None and self.address_group is None: | ||
| raise ValueError( | ||
| "One of either AddressGroupId or AddressGroup is required." | ||
| ) | ||
|
|
||
| if self.message_template_id is None and self.message_template is None: | ||
| raise ValueError( | ||
| "One of either MessageTemplateId or MessageTemplate is required." | ||
| ) | ||
|
|
||
| return self | ||
16 changes: 16 additions & 0 deletions
16
nisystemlink/clients/notification/models/_dynamic_notification_strategy.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| from typing import Annotated, List | ||
|
|
||
|
|
||
| from nisystemlink.clients.core._uplink._json_model import JsonModel | ||
| from pydantic import Field | ||
|
|
||
| from ._dynamic_notification_configuration import DynamicNotificationConfiguration | ||
|
|
||
|
|
||
| class DynamicNotificationStrategy(JsonModel): | ||
| """Model for the notification strategy to be applied.""" | ||
|
|
||
| notification_configurations: Annotated[ | ||
| List[DynamicNotificationConfiguration], Field(min_length=1) | ||
| ] | ||
| """Notification configurations associated with this strategy.""" |
18 changes: 18 additions & 0 deletions
18
nisystemlink/clients/notification/models/_dynamic_strategy_request.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| from typing import Dict | ||
|
|
||
| from nisystemlink.clients.core._uplink._json_model import JsonModel | ||
|
|
||
| from ._dynamic_notification_strategy import DynamicNotificationStrategy | ||
|
|
||
|
|
||
| class DynamicStrategyRequest(JsonModel): | ||
| """Request model for applying a dynamic notification strategy.""" | ||
|
|
||
| message_template_substitution_fields: Dict[str, str] | None = None | ||
| """Defines the fields used for substituting values in the message template. | ||
|
|
||
| Example: { "replacement": "value" } | ||
| """ | ||
|
|
||
| notification_strategy: DynamicNotificationStrategy | ||
| """Notification strategy containing configurations for address groups and message templates.""" |
13 changes: 13 additions & 0 deletions
13
nisystemlink/clients/notification/models/_message_template.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| from typing import Dict | ||
|
|
||
| from ._base_notification_metadata import BaseNotificationMetadata | ||
|
|
||
|
|
||
| class MessageTemplate(BaseNotificationMetadata): | ||
| """Model defining the notification content structure.""" | ||
|
|
||
| interpreting_service_name: str | ||
| """Name of the interpreting service""" | ||
|
|
||
| fields: Dict[str, str] | ||
| """Template fields for message.""" |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.