Skip to content

Commit 47bc4e3

Browse files
Venkatakrishnan774lokeshkumarkuntalVenkatakrishnan774
authored
feat: added output management (#253)
Co-authored-by: I555296 <lokesh.kumar.kuntal@sap.com> Co-authored-by: Venkatakrishnan774 <s.venkatakrishnan01+sap@sap.com>
1 parent a558a8e commit 47bc4e3

31 files changed

Lines changed: 5461 additions & 4 deletions

.env_integration_tests.example

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,11 @@ CLOUD_SDK_CFG_OBJECTSTORE_DEFAULT_HOST=your-objectstore-host-here
6262
CLOUD_SDK_CFG_OBJECTSTORE_DEFAULT_ACCESS_KEY_ID=your-access-key-id-here
6363
CLOUD_SDK_CFG_OBJECTSTORE_DEFAULT_SECRET_ACCESS_KEY=your-secret-access-key-here
6464
CLOUD_SDK_CFG_OBJECTSTORE_DEFAULT_BUCKET=your-bucket-name-here
65+
66+
# OUTPUT MANAGEMENT
67+
# For cloud mode (destination-based):
68+
CLOUD_SDK_OMS_DESTINATION_NAME=your-output-management-destination-name-here
69+
CLOUD_SDK_OMS_ACCESS_STRATEGY=PROVIDER_ONLY
70+
CLOUD_SDK_OMS_INSTANCE=default
71+
# For local mode (no credentials needed):
72+
# CLOUD_SDK_OMS_TEST_MODE=local

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "sap-cloud-sdk"
3-
version = "0.39.1"
3+
version = "0.40.0"
44
description = "SAP Cloud SDK for Python"
55
readme = "README.md"
66
license = "Apache-2.0"
@@ -37,6 +37,7 @@ dependencies = [
3737
"opentelemetry-instrumentation-django~=0.63b1",
3838
"opentelemetry-instrumentation-flask~=0.63b1",
3939
"mcp>=1.1.0",
40+
"cryptography>=46.0.3",
4041
]
4142

4243
[project.optional-dependencies]

src/sap_cloud_sdk/core/telemetry/module.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class Module(str, Enum):
1818
DMS = "dms"
1919
EXTENSIBILITY = "extensibility"
2020
OBJECTSTORE = "objectstore"
21+
OUTPUT_MANAGEMENT = "outputmanagement"
2122
PRINT = "print"
2223
TELEMETRY = "telemetry"
2324

src/sap_cloud_sdk/core/telemetry/operation.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,5 +209,10 @@ class Operation(str, Enum):
209209
AGENT_MEMORY_GET_RETENTION_CONFIG = "get_retention_config"
210210
AGENT_MEMORY_UPDATE_RETENTION_CONFIG = "update_retention_config"
211211

212+
# Output Management Operations
213+
OUTPUT_MANAGEMENT_SEND_EMAIL = "send_email"
214+
OUTPUT_MANAGEMENT_SEND_EMAIL_WITH_MCP = "send_email_with_mcp"
215+
OUTPUT_MANAGEMENT_SEND_OUTPUT_REQUEST = "send_output_request"
216+
212217
def __str__(self) -> str:
213218
return self.value
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
"""SAP Ariba Output Management Service SDK for Python."""
2+
3+
import logging
4+
import os
5+
from typing import Optional
6+
7+
from .client import OutputManagementClient
8+
from ._service_client import OutputManagementServiceClient
9+
from ._models import (
10+
OutputRequest,
11+
OutputRequestBuilder,
12+
OutputResponse,
13+
EmailConfiguration,
14+
AttachmentConfig,
15+
OutputManagementInfo,
16+
OutputRequestData,
17+
DirectShareConfiguration,
18+
FormConfiguration,
19+
PreGeneratedAttachment,
20+
)
21+
from .config import DestinationCredentialConfig
22+
from .constants import FileFormat, Channel
23+
from .exceptions import (
24+
OutputManagementException,
25+
AuthenticationException,
26+
ValidationException,
27+
NetworkException,
28+
DestinationNotFoundException,
29+
DestinationAccessException,
30+
)
31+
32+
logger = logging.getLogger(__name__)
33+
34+
35+
def create_client(
36+
destination_credential_config: Optional[DestinationCredentialConfig] = None,
37+
destination_name: Optional[str] = None,
38+
access_strategy: Optional[str] = None,
39+
instance: Optional[str] = None,
40+
) -> OutputManagementClient:
41+
"""
42+
Create an Output Management client with configuration from environment or parameters.
43+
44+
This is the recommended factory function for creating clients. It follows the SDK's
45+
standard pattern of reading configuration from environment variables with optional overrides.
46+
47+
Environment Variables:
48+
- CLOUD_SDK_OMS_DESTINATION_NAME: Default destination name
49+
- CLOUD_SDK_OMS_ACCESS_STRATEGY: Default access strategy (PROVIDER_ONLY or SUBSCRIBER_ONLY)
50+
- CLOUD_SDK_OMS_INSTANCE: Default destination service instance name
51+
52+
Args:
53+
destination_credential_config: Pre-configured DestinationCredentialConfig object.
54+
If provided, other parameters are ignored.
55+
destination_name: Name of the destination. If not provided, reads from
56+
CLOUD_SDK_OMS_DESTINATION_NAME environment variable.
57+
access_strategy: Destination access strategy. If not provided, reads from
58+
CLOUD_SDK_OMS_ACCESS_STRATEGY environment variable or defaults to "PROVIDER_ONLY".
59+
instance: Destination service instance name. If not provided, reads from
60+
CLOUD_SDK_OMS_INSTANCE environment variable or defaults to "default".
61+
62+
Returns:
63+
Configured OutputManagementClient instance
64+
65+
Raises:
66+
ValidationException: If destination_name is not provided and not found in environment
67+
(when destination_credential_config is not provided)
68+
69+
Example:
70+
```python
71+
from sap_cloud_sdk.outputmanagement import create_client, DestinationCredentialConfig
72+
73+
# Using environment variables
74+
client = create_client()
75+
76+
# With explicit parameters
77+
client = create_client(
78+
destination_name="MY_OMS_DESTINATION",
79+
access_strategy="PROVIDER_ONLY",
80+
instance="default"
81+
)
82+
83+
# With DestinationCredentialConfig
84+
config = DestinationCredentialConfig(
85+
destination_name="MY_OMS_DESTINATION",
86+
access_strategy="PROVIDER_ONLY",
87+
instance="default"
88+
)
89+
client = create_client(destination_credential_config=config)
90+
91+
# Use the client's 4 methods
92+
response = client.send_email(
93+
notification_template_key="PO_NOTIFICATION",
94+
to=["user@example.com"],
95+
business_document={"PurchaseOrder": {"id": "PO-123"}}
96+
)
97+
```
98+
"""
99+
# If destination_credential_config is provided, use it directly
100+
if destination_credential_config is not None:
101+
destination_config = destination_credential_config
102+
logger.info(
103+
f"Creating Output Management client with provided DestinationCredentialConfig: "
104+
f"destination '{destination_config.destination_name}'"
105+
)
106+
else:
107+
# Validate and build config from individual parameters
108+
# Read from environment variables with parameter overrides
109+
dest_name = destination_name or os.getenv("CLOUD_SDK_OMS_DESTINATION_NAME")
110+
access_strat = access_strategy or os.getenv(
111+
"CLOUD_SDK_OMS_ACCESS_STRATEGY", "PROVIDER_ONLY"
112+
)
113+
inst = instance or os.getenv("CLOUD_SDK_OMS_INSTANCE", "default")
114+
115+
if not dest_name:
116+
raise ValidationException(
117+
"Destination name must be provided either as parameter or via "
118+
"CLOUD_SDK_OMS_DESTINATION_NAME environment variable",
119+
error_code="MISSING_DESTINATION_NAME",
120+
)
121+
122+
logger.info(
123+
f"Creating Output Management client with destination '{dest_name}', "
124+
f"access_strategy '{access_strat}', instance '{inst}'"
125+
)
126+
127+
# Create destination config
128+
destination_config = DestinationCredentialConfig(
129+
destination_name=dest_name,
130+
access_strategy=access_strat,
131+
instance=inst,
132+
)
133+
134+
# Get the destination object
135+
http_destination = destination_config.get_destination()
136+
137+
# Get the base URL from destination
138+
base_url = destination_config.get_base_url()
139+
logger.info(f"Retrieved destination base URL: {base_url}")
140+
141+
# Create service client directly
142+
service_client = OutputManagementServiceClient(
143+
base_url=base_url,
144+
destination=http_destination,
145+
destination_instance=destination_config.instance or "default",
146+
)
147+
148+
# Wrap it in the unified OutputManagementClient
149+
return OutputManagementClient(service_client)
150+
151+
152+
__all__ = [
153+
# Main client and factory function
154+
"OutputManagementClient",
155+
"create_client",
156+
# Models
157+
"OutputRequest",
158+
"OutputRequestBuilder",
159+
"OutputResponse",
160+
"EmailConfiguration",
161+
"AttachmentConfig",
162+
"OutputManagementInfo",
163+
"OutputRequestData",
164+
"DirectShareConfiguration",
165+
"FormConfiguration",
166+
"PreGeneratedAttachment",
167+
# Configuration
168+
"DestinationCredentialConfig",
169+
# Constants/Enums
170+
"FileFormat",
171+
"Channel",
172+
# Exceptions
173+
"OutputManagementException",
174+
"AuthenticationException",
175+
"ValidationException",
176+
"NetworkException",
177+
"DestinationNotFoundException",
178+
"DestinationAccessException",
179+
]

0 commit comments

Comments
 (0)