chore: import upstream snapshot with attribution
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run

This commit is contained in:
wehub-resource-sync
2026-07-13 13:21:23 +08:00
commit b957a53def
5423 changed files with 863745 additions and 0 deletions
@@ -0,0 +1,14 @@
# Copyright (c) Microsoft. All rights reserved.
from semantic_kernel.utils.feature_stage_decorator import experimental
@experimental
class RestApiExpectedResponse:
"""RestApiExpectedResponse."""
def __init__(self, description: str, media_type: str, schema: dict[str, str] | None = None):
"""Initialize the RestApiExpectedResponse."""
self.description = description
self.media_type = media_type
self.schema = schema
@@ -0,0 +1,16 @@
# Copyright (c) Microsoft. All rights reserved.
from dataclasses import dataclass
from semantic_kernel.utils.feature_stage_decorator import experimental
@experimental
@dataclass
class RestApiOAuthFlow:
"""Represents the OAuth flow used by the REST API."""
authorization_url: str
token_url: str
scopes: dict[str, str]
refresh_url: str | None = None
@@ -0,0 +1,17 @@
# Copyright (c) Microsoft. All rights reserved.
from dataclasses import dataclass
from semantic_kernel.connectors.openapi_plugin.models.rest_api_oauth_flow import RestApiOAuthFlow
from semantic_kernel.utils.feature_stage_decorator import experimental
@experimental
@dataclass
class RestApiOAuthFlows:
"""Represents the OAuth flows used by the REST API."""
implicit: RestApiOAuthFlow | None = None
password: RestApiOAuthFlow | None = None
client_credentials: RestApiOAuthFlow | None = None
authorization_code: RestApiOAuthFlow | None = None
@@ -0,0 +1,552 @@
# Copyright (c) Microsoft. All rights reserved.
import re
from typing import Any, Final
from urllib.parse import ParseResult, ParseResultBytes, quote, unquote, urlencode, urljoin, urlparse, urlunparse
from semantic_kernel.connectors.openapi_plugin.models.rest_api_expected_response import (
RestApiExpectedResponse,
)
from semantic_kernel.connectors.openapi_plugin.models.rest_api_parameter import RestApiParameter
from semantic_kernel.connectors.openapi_plugin.models.rest_api_parameter_location import (
RestApiParameterLocation,
)
from semantic_kernel.connectors.openapi_plugin.models.rest_api_parameter_style import (
RestApiParameterStyle,
)
from semantic_kernel.connectors.openapi_plugin.models.rest_api_payload import RestApiPayload
from semantic_kernel.connectors.openapi_plugin.models.rest_api_payload_property import (
RestApiPayloadProperty,
)
from semantic_kernel.connectors.openapi_plugin.models.rest_api_security_requirement import RestApiSecurityRequirement
from semantic_kernel.exceptions.function_exceptions import FunctionExecutionException
from semantic_kernel.functions.kernel_parameter_metadata import KernelParameterMetadata
from semantic_kernel.utils.feature_stage_decorator import experimental
@experimental
class RestApiOperation:
"""RestApiOperation."""
MEDIA_TYPE_TEXT_PLAIN = "text/plain"
PAYLOAD_ARGUMENT_NAME = "payload"
CONTENT_TYPE_ARGUMENT_NAME = "content-type"
INVALID_SYMBOLS_REGEX = re.compile(r"[^0-9A-Za-z_]+")
_preferred_responses: Final[list[str]] = [
"200",
"201",
"202",
"203",
"204",
"205",
"206",
"207",
"208",
"226",
"2XX",
"default",
]
def __init__(
self,
id: str,
method: str,
servers: list[dict[str, Any]],
path: str,
summary: str | None = None,
description: str | None = None,
params: list["RestApiParameter"] | None = None,
request_body: "RestApiPayload | None" = None,
responses: dict[str, "RestApiExpectedResponse"] | None = None,
security_requirements: list[RestApiSecurityRequirement] | None = None,
):
"""Initialize the RestApiOperation."""
self._id = id
self._method = method.upper()
self._servers = servers
self._path = path
self._summary = summary
self._description = description
self._parameters = params if params else []
self._request_body = request_body
self._responses = responses
self._security_requirements = security_requirements
self._is_frozen = False
def freeze(self):
"""Make the instance and its components immutable."""
self._is_frozen = True
if self.request_body:
self.request_body.freeze()
for param in self.parameters:
param.freeze()
def _throw_if_frozen(self):
"""Raise an exception if the object is frozen."""
if self._is_frozen:
raise FunctionExecutionException(
f"The `RestApiOperation` instance with id {self.id} is frozen and cannot be modified."
)
@property
def id(self):
"""Get the ID of the operation."""
return self._id
@id.setter
def id(self, value: str):
self._throw_if_frozen()
self._id = value
@property
def method(self):
"""Get the method of the operation."""
return self._method
@method.setter
def method(self, value: str):
self._throw_if_frozen()
self._method = value
@property
def servers(self):
"""Get the servers of the operation."""
return self._servers
@servers.setter
def servers(self, value: list[dict[str, Any]]):
self._throw_if_frozen()
self._servers = value
@property
def path(self):
"""Get the path of the operation."""
return self._path
@path.setter
def path(self, value: str):
self._throw_if_frozen()
self._path = value
@property
def summary(self):
"""Get the summary of the operation."""
return self._summary
@summary.setter
def summary(self, value: str | None):
self._throw_if_frozen()
self._summary = value
@property
def description(self):
"""Get the description of the operation."""
return self._description
@description.setter
def description(self, value: str | None):
self._throw_if_frozen()
self._description = value
@property
def parameters(self):
"""Get the parameters of the operation."""
return self._parameters
@parameters.setter
def parameters(self, value: list["RestApiParameter"]):
self._throw_if_frozen()
self._parameters = value
@property
def request_body(self):
"""Get the request body of the operation."""
return self._request_body
@request_body.setter
def request_body(self, value: "RestApiPayload | None"):
self._throw_if_frozen()
self._request_body = value
@property
def responses(self):
"""Get the responses of the operation."""
return self._responses
@responses.setter
def responses(self, value: dict[str, "RestApiExpectedResponse"] | None):
self._throw_if_frozen()
self._responses = value
@property
def security_requirements(self):
"""Get the security requirements of the operation."""
return self._security_requirements
@security_requirements.setter
def security_requirements(self, value: list[RestApiSecurityRequirement] | None):
self._throw_if_frozen()
self._security_requirements = value
def url_join(self, base_url: str, path: str):
"""Join a base URL and a path, correcting for any missing slashes."""
parsed_base = urlparse(base_url)
base_path = parsed_base.path + "/" if not parsed_base.path.endswith("/") else parsed_base.path
full_path = urljoin(base_path, path.lstrip("/"))
return urlunparse(parsed_base._replace(path=full_path))
def build_headers(self, arguments: dict[str, Any]) -> dict[str, str]:
"""Build the headers for the operation."""
headers = {}
parameters = [p for p in self.parameters if p.location == RestApiParameterLocation.HEADER]
for parameter in parameters:
argument = arguments.get(parameter.name)
if argument is None:
if parameter.is_required:
raise FunctionExecutionException(
f"No argument is provided for the `{parameter.name}` "
f"required parameter of the operation - `{self.id}`."
)
continue
headers[parameter.name] = str(argument)
return headers
def build_operation_url(self, arguments, server_url_override=None, api_host_url=None):
"""Build the URL for the operation."""
server_url = self.get_server_url(server_url_override, api_host_url, arguments)
path = self.build_path(self.path, arguments)
try:
request_url = urljoin(server_url, path.lstrip("/"))
except Exception as e:
raise FunctionExecutionException(f"Error building the URL for the operation {self.id}: {e!s}") from e
self._ensure_request_target_matches_server(server_url, request_url)
return request_url
@staticmethod
def _ensure_request_target_matches_server(server_url: str, request_url: str) -> None:
"""Verify URL construction did not move the request off the configured server.
A selected operation path must resolve to a request on the same scheme, host, and port and
within the server's base path. Otherwise an absolute or authority-changing operation path
(for example "https://another-host/admin") could redirect a credential-bearing request to an
unintended target even though it carries no dot-segment. This complements
`_validate_path_segments` so operation selection, path validation, and request construction
share one canonical target.
"""
server = urlparse(server_url)
request = urlparse(request_url)
if (request.scheme, request.username, request.password, request.hostname, request.port) != (
server.scheme,
server.username,
server.password,
server.hostname,
server.port,
):
raise FunctionExecutionException(
f"The operation path resolves to '{request.scheme}://{request.netloc}', which does not match "
f"the configured server '{server.scheme}://{server.netloc}'."
)
# get_server_url guarantees a trailing slash, so the server base path always ends with "/".
base_path = server.path
if request.path != base_path.rstrip("/") and not request.path.startswith(base_path):
raise FunctionExecutionException(
f"The operation path resolves to '{request.path}', which is outside the configured server "
f"base path '{base_path}'."
)
def get_server_url(self, server_url_override=None, api_host_url=None, arguments=None):
"""Get the server URL for the operation."""
if arguments is None:
arguments = {}
# Prioritize server_url_override
if (
server_url_override is not None
and isinstance(server_url_override, (ParseResult, ParseResultBytes))
and server_url_override.geturl() != b""
):
server_url_string = server_url_override.geturl()
elif server_url_override is not None and isinstance(server_url_override, str) and server_url_override != "":
server_url_string = server_url_override
elif self.servers and len(self.servers) > 0:
# Use the first server by default
server = self.servers[0]
server_url_string = server["url"] if isinstance(server, dict) else server
server_variables = server.get("variables", {}) if isinstance(server, dict) else {}
# Substitute server variables if available
for variable_name, variable_def in server_variables.items():
argument_name = variable_def.get("argument_name", variable_name)
allowed_values = variable_def.get("enum")
if argument_name in arguments:
value = str(arguments[argument_name])
elif "default" in variable_def and variable_def["default"] is not None:
# Use the default value if no argument is provided
value = str(variable_def["default"])
else:
# Raise an exception if no value is available
raise FunctionExecutionException(
f"No argument provided for the '{variable_name}' server variable of the operation '{self.id}'."
)
if allowed_values is not None and value not in allowed_values:
raise FunctionExecutionException(
f"Value '{value}' for server variable '{variable_name}' is not one of the allowed values."
)
server_url_string = server_url_string.replace(f"{{{variable_name}}}", quote(value, safe=""))
elif self.server_url:
server_url_string = self.server_url
elif api_host_url is not None:
server_url_string = api_host_url
else:
raise FunctionExecutionException(f"No valid server URL for operation {self.id}")
# Ensure the base URL ends with a trailing slash
if not server_url_string.endswith("/"):
server_url_string += "/"
return server_url_string # Return the URL string directly
def build_path(self, path_template: str, arguments: dict[str, Any]) -> str:
"""Build the path for the operation."""
parameters = [p for p in self.parameters if p.location == RestApiParameterLocation.PATH]
for parameter in parameters:
argument = arguments.get(parameter.name)
if argument is None:
if parameter.is_required:
raise FunctionExecutionException(
f"No argument is provided for the `{parameter.name}` "
f"required parameter of the operation - `{self.id}`."
)
continue
path_template = path_template.replace(f"{{{parameter.name}}}", quote(str(argument), safe=""))
self._validate_path_segments(path_template)
return path_template
@staticmethod
def _validate_path_segments(path: str) -> None:
"""Reject dot-segments (. or ..), including percent-encoded forms, that enable path traversal.
The operation is selected using the raw path but the request URL is built from a canonicalized
path, so encoded dot-segments such as "%2e%2e" must be rejected before the URL is constructed.
"""
if RestApiOperation._contains_dot_segment(path):
raise FunctionExecutionException(
f"Path '{path}' contains a dot-segment, which could lead to path traversal."
)
@staticmethod
def _contains_dot_segment(path: str) -> bool:
"""Return True if the path contains a dot-segment (. or ..), including percent-encoded forms.
Used both to reject such paths when building a request URL and to exclude them during operation
selection so an encoded dot-segment cannot bypass an include/exclude operation-selection filter.
"""
if not path:
return False
for segment in path.split("/"):
decoded = segment
for _ in range(5):
unescaped = unquote(decoded)
if unescaped == decoded:
break
decoded = unescaped
# A decoded segment may contain encoded separators ("%2f"/"%5c"), so re-split on
# both "/" and "\" and reject any resulting dot-segment.
for part in decoded.replace("\\", "/").split("/"):
if part in (".", ".."):
return True
return False
@staticmethod
def _is_non_relative_path(path: str) -> bool:
"""Return True if the path is non-relative (absolute or authority-changing).
A conformant OpenAPI operation path is relative to the server URL. An absolute URI, a
protocol-relative reference ("//host"), or a backslash-authority reference changes the request
target once combined with the server URL, so such a path is excluded during operation selection
to keep selection and request construction on one canonical target.
"""
if not path:
return False
if path.startswith(("//", "\\\\", "/\\", "\\/")):
return True
parsed = urlparse(path)
return bool(parsed.scheme or parsed.netloc)
def build_query_string(self, arguments: dict[str, Any]) -> str:
"""Build the query string for the operation."""
segments = []
parameters = [p for p in self.parameters if p.location == RestApiParameterLocation.QUERY]
for parameter in parameters:
argument = arguments.get(parameter.name)
if argument is None:
if parameter.is_required:
raise FunctionExecutionException(
f"No argument or value is provided for the `{parameter.name}` "
f"required parameter of the operation - `{self.id}`."
)
continue
segments.append((parameter.name, argument))
return urlencode(segments)
def replace_invalid_symbols(self, parameter_name):
"""Replace invalid symbols in the parameter name with underscores."""
return RestApiOperation.INVALID_SYMBOLS_REGEX.sub("_", parameter_name)
def get_parameters(
self,
operation: "RestApiOperation",
add_payload_params_from_metadata: bool = True,
enable_payload_spacing: bool = False,
) -> list["RestApiParameter"]:
"""Get the parameters for the operation."""
params = list(operation.parameters) if operation.parameters is not None else []
if operation.request_body is not None:
params.extend(
self.get_payload_parameters(
operation=operation,
use_parameters_from_metadata=add_payload_params_from_metadata,
enable_namespacing=enable_payload_spacing,
)
)
for parameter in params:
parameter.alternative_name = self.replace_invalid_symbols(parameter.name)
return params
def create_payload_artificial_parameter(self, operation: "RestApiOperation") -> "RestApiParameter":
"""Create an artificial parameter for the REST API request body."""
return RestApiParameter(
name=self.PAYLOAD_ARGUMENT_NAME,
type=(
"string"
if operation.request_body
and operation.request_body.media_type == RestApiOperation.MEDIA_TYPE_TEXT_PLAIN
else "object"
),
is_required=True,
location=RestApiParameterLocation.BODY,
style=RestApiParameterStyle.SIMPLE,
description=operation.request_body.description if operation.request_body else "REST API request body.",
schema=operation.request_body.schema if operation.request_body else None,
)
def create_content_type_artificial_parameter(self) -> "RestApiParameter":
"""Create an artificial parameter for the content type of the REST API request body."""
return RestApiParameter(
name=self.CONTENT_TYPE_ARGUMENT_NAME,
type="string",
is_required=False,
location=RestApiParameterLocation.BODY,
style=RestApiParameterStyle.SIMPLE,
description="Content type of REST API request body.",
)
def _get_property_name(self, property: RestApiPayloadProperty, root_property_name: bool, enable_namespacing: bool):
if enable_namespacing and root_property_name:
return f"{root_property_name}.{property.name}"
return property.name
def _get_parameters_from_payload_metadata(
self,
properties: list["RestApiPayloadProperty"],
enable_namespacing: bool = False,
root_property_name: bool | None = None,
) -> list["RestApiParameter"]:
parameters: list[RestApiParameter] = []
for property in properties:
parameter_name = self._get_property_name(property, root_property_name or False, enable_namespacing)
if not hasattr(property, "properties") or not property.properties:
parameters.append(
RestApiParameter(
name=parameter_name,
type=property.type,
is_required=property.is_required,
location=RestApiParameterLocation.BODY,
style=RestApiParameterStyle.SIMPLE,
description=property.description,
schema=property.schema,
)
)
else:
# Handle property.properties as a single instance or a list
if isinstance(property.properties, RestApiPayloadProperty):
nested_properties = [property.properties]
else:
nested_properties = property.properties
parameters.extend(
self._get_parameters_from_payload_metadata(nested_properties, enable_namespacing, parameter_name)
)
return parameters
def get_payload_parameters(
self, operation: "RestApiOperation", use_parameters_from_metadata: bool, enable_namespacing: bool
):
"""Get the payload parameters for the operation."""
if use_parameters_from_metadata:
if operation.request_body is None:
raise Exception(
f"Payload parameters cannot be retrieved from the `{operation.id}` "
f"operation payload metadata because it is missing."
)
if operation.request_body.media_type == RestApiOperation.MEDIA_TYPE_TEXT_PLAIN:
return [self.create_payload_artificial_parameter(operation)]
return self._get_parameters_from_payload_metadata(operation.request_body.properties, enable_namespacing)
return [
self.create_payload_artificial_parameter(operation),
self.create_content_type_artificial_parameter(),
]
def get_default_response(
self, responses: dict[str, RestApiExpectedResponse], preferred_responses: list[str]
) -> RestApiExpectedResponse | None:
"""Get the default response for the operation.
If no appropriate response is found, returns None.
"""
for code in preferred_responses:
if code in responses:
return responses[code]
return None
def get_default_return_parameter(self, preferred_responses: list[str] | None = None) -> KernelParameterMetadata:
"""Get the default return parameter for the operation."""
if preferred_responses is None:
preferred_responses = self._preferred_responses
responses = self.responses if self.responses is not None else {}
rest_operation_response = self.get_default_response(responses, preferred_responses)
schema_type = None
if rest_operation_response is not None and rest_operation_response.schema is not None:
schema_type = rest_operation_response.schema.get("type")
if rest_operation_response:
return KernelParameterMetadata(
name="return",
description=rest_operation_response.description,
type_=schema_type,
schema_data=rest_operation_response.schema,
)
return KernelParameterMetadata(
name="return",
description="Default return parameter",
type_="string",
schema_data={"type": "string"},
)
@@ -0,0 +1,155 @@
# Copyright (c) Microsoft. All rights reserved.
from typing import Any
from semantic_kernel.connectors.openapi_plugin.models.rest_api_expected_response import (
RestApiExpectedResponse,
)
from semantic_kernel.connectors.openapi_plugin.models.rest_api_parameter_location import (
RestApiParameterLocation,
)
from semantic_kernel.connectors.openapi_plugin.models.rest_api_parameter_style import (
RestApiParameterStyle,
)
from semantic_kernel.exceptions.function_exceptions import FunctionExecutionException
from semantic_kernel.utils.feature_stage_decorator import experimental
@experimental
class RestApiParameter:
"""RestApiParameter."""
def __init__(
self,
name: str,
type: str,
location: RestApiParameterLocation,
style: RestApiParameterStyle | None = None,
alternative_name: str | None = None,
description: str | None = None,
is_required: bool = False,
default_value: Any | None = None,
schema: str | dict | None = None,
response: RestApiExpectedResponse | None = None,
):
"""Initialize the RestApiParameter."""
self._name = name
self._type = type
self._location = location
self._style = style
self._alternative_name = alternative_name
self._description = description
self._is_required = is_required
self._default_value = default_value
self._schema = schema
self._response = response
self._is_frozen = False
def freeze(self):
"""Make the instance immutable."""
self._is_frozen = True
def _throw_if_frozen(self):
"""Raise an exception if the object is frozen."""
if self._is_frozen:
raise FunctionExecutionException("This `RestApiParameter` instance is frozen and cannot be modified.")
@property
def name(self):
"""Get the name of the parameter."""
return self._name
@name.setter
def name(self, value: str):
self._throw_if_frozen()
self._name = value
@property
def type(self):
"""Get the type of the parameter."""
return self._type
@type.setter
def type(self, value: str):
self._throw_if_frozen()
self._type = value
@property
def location(self):
"""Get the location of the parameter."""
return self._location
@location.setter
def location(self, value: RestApiParameterLocation):
self._throw_if_frozen()
self._location = value
@property
def style(self):
"""Get the style of the parameter."""
return self._style
@style.setter
def style(self, value: RestApiParameterStyle | None):
self._throw_if_frozen()
self._style = value
@property
def alternative_name(self):
"""Get the alternative name of the parameter."""
return self._alternative_name
@alternative_name.setter
def alternative_name(self, value: str | None):
self._throw_if_frozen()
self._alternative_name = value
@property
def description(self):
"""Get the description of the parameter."""
return self._description
@description.setter
def description(self, value: str | None):
self._throw_if_frozen()
self._description = value
@property
def is_required(self):
"""Get whether the parameter is required."""
return self._is_required
@is_required.setter
def is_required(self, value: bool):
self._throw_if_frozen()
self._is_required = value
@property
def default_value(self):
"""Get the default value of the parameter."""
return self._default_value
@default_value.setter
def default_value(self, value: Any | None):
self._throw_if_frozen()
self._default_value = value
@property
def schema(self):
"""Get the schema of the parameter."""
return self._schema
@schema.setter
def schema(self, value: str | dict | None):
self._throw_if_frozen()
self._schema = value
@property
def response(self):
"""Get the response of the parameter."""
return self._response
@response.setter
def response(self, value: Any | None):
self._throw_if_frozen()
self._response = value
@@ -0,0 +1,16 @@
# Copyright (c) Microsoft. All rights reserved.
from enum import Enum
from semantic_kernel.utils.feature_stage_decorator import experimental
@experimental
class RestApiParameterLocation(Enum):
"""The location of the REST API parameter."""
PATH = "path"
QUERY = "query"
HEADER = "header"
COOKIE = "cookie"
BODY = "body"
@@ -0,0 +1,12 @@
# Copyright (c) Microsoft. All rights reserved.
from enum import Enum
from semantic_kernel.utils.feature_stage_decorator import experimental
@experimental
class RestApiParameterStyle(Enum):
"""RestApiParameterStyle."""
SIMPLE = "simple"
@@ -0,0 +1,77 @@
# Copyright (c) Microsoft. All rights reserved.
from semantic_kernel.connectors.openapi_plugin.models.rest_api_payload_property import (
RestApiPayloadProperty,
)
from semantic_kernel.exceptions.function_exceptions import FunctionExecutionException
from semantic_kernel.utils.feature_stage_decorator import experimental
@experimental
class RestApiPayload:
"""RestApiPayload."""
def __init__(
self,
media_type: str,
properties: list[RestApiPayloadProperty],
description: str | None = None,
schema: str | None = None,
):
"""Initialize the RestApiPayload."""
self._media_type = media_type
self._properties = properties
self._description = description
self._schema = schema
self._is_frozen = False
def freeze(self):
"""Make the instance immutable and freeze properties."""
self._is_frozen = True
for property in self._properties:
property.freeze()
def _throw_if_frozen(self):
"""Raise an exception if the object is frozen."""
if self._is_frozen:
raise FunctionExecutionException("This `RestApiPayload` instance is frozen and cannot be modified.")
@property
def media_type(self):
"""Get the media type of the payload."""
return self._media_type
@media_type.setter
def media_type(self, value: str):
self._throw_if_frozen()
self._media_type = value
@property
def description(self):
"""Get the description of the payload."""
return self._description
@description.setter
def description(self, value: str | None):
self._throw_if_frozen()
self._description = value
@property
def properties(self):
"""Get the properties of the payload."""
return self._properties
@properties.setter
def properties(self, value: list[RestApiPayloadProperty]):
self._throw_if_frozen()
self._properties = value
@property
def schema(self):
"""Get the schema of the payload."""
return self._schema
@schema.setter
def schema(self, value: str | None):
self._throw_if_frozen()
self._schema = value
@@ -0,0 +1,112 @@
# Copyright (c) Microsoft. All rights reserved.
from typing import Any
from semantic_kernel.exceptions.function_exceptions import FunctionExecutionException
from semantic_kernel.utils.feature_stage_decorator import experimental
@experimental
class RestApiPayloadProperty:
"""RestApiPayloadProperty."""
def __init__(
self,
name: str,
type: str,
properties: list["RestApiPayloadProperty"] | None = None,
description: str | None = None,
is_required: bool = False,
default_value: Any | None = None,
schema: str | None = None,
):
"""Initialize the RestApiPayloadProperty."""
self._name = name
self._type = type
self._properties = properties or []
self._description = description
self._is_required = is_required
self._default_value = default_value
self._schema = schema
self._is_frozen = False
def freeze(self):
"""Make the instance immutable, and freeze nested properties."""
self._is_frozen = True
for prop in self._properties:
prop.freeze()
def _throw_if_frozen(self):
"""Raise an exception if the object is frozen."""
if self._is_frozen:
raise FunctionExecutionException("This instance is frozen and cannot be modified.")
@property
def name(self):
"""Get the name of the property."""
return self._name
@name.setter
def name(self, value: str):
self._throw_if_frozen()
self._name = value
@property
def type(self):
"""Get the type of the property."""
return self._type
@type.setter
def type(self, value: str):
self._throw_if_frozen()
self._type = value
@property
def properties(self):
"""Get the properties of the property."""
return self._properties
@properties.setter
def properties(self, value: list["RestApiPayloadProperty"]):
self._throw_if_frozen()
self._properties = value
@property
def description(self):
"""Get the description of the property."""
return self._description
@description.setter
def description(self, value: str | None):
self._throw_if_frozen()
self._description = value
@property
def is_required(self):
"""Get whether the property is required."""
return self._is_required
@is_required.setter
def is_required(self, value: bool):
self._throw_if_frozen()
self._is_required = value
@property
def default_value(self):
"""Get the default value of the property."""
return self._default_value
@default_value.setter
def default_value(self, value: Any | None):
self._throw_if_frozen()
self._default_value = value
@property
def schema(self):
"""Get the schema of the property."""
return self._schema
@schema.setter
def schema(self, value: str | None):
self._throw_if_frozen()
self._schema = value
@@ -0,0 +1,19 @@
# Copyright (c) Microsoft. All rights reserved.
class RestApiRunOptions:
"""The options for running the REST API operation."""
def __init__(
self, server_url_override: str | None = None, api_host_url: str | None = None, timeout: float | None = None
) -> None:
"""Initialize the REST API operation run options.
Args:
server_url_override: The server URL override, if any.
api_host_url: The API host URL, if any.
timeout: The timeout for the operation, if any.
"""
self.server_url_override: str | None = server_url_override
self.api_host_url: str | None = api_host_url
self.timeout: float | None = timeout
@@ -0,0 +1,13 @@
# Copyright (c) Microsoft. All rights reserved.
from semantic_kernel.connectors.openapi_plugin.models.rest_api_security_scheme import RestApiSecurityScheme
from semantic_kernel.utils.feature_stage_decorator import experimental
@experimental
class RestApiSecurityRequirement(dict[RestApiSecurityScheme, list[str]]):
"""Represents the security requirements used by the REST API."""
def __init__(self, dictionary: dict[RestApiSecurityScheme, list[str]]):
"""Initializes a new instance of the RestApiSecurityRequirement class."""
super().__init__(dictionary)
@@ -0,0 +1,33 @@
# Copyright (c) Microsoft. All rights reserved.
from semantic_kernel.connectors.openapi_plugin.models.rest_api_oauth_flows import RestApiOAuthFlows
from semantic_kernel.connectors.openapi_plugin.models.rest_api_parameter_location import (
RestApiParameterLocation,
)
from semantic_kernel.utils.feature_stage_decorator import experimental
@experimental
class RestApiSecurityScheme:
"""Represents the security scheme used by the REST API."""
def __init__(
self,
security_scheme_type: str,
name: str,
in_: RestApiParameterLocation,
scheme: str,
open_id_connect_url: str,
description: str | None = None,
bearer_format: str | None = None,
flows: RestApiOAuthFlows | None = None,
):
"""Initializes a new instance of the RestApiSecurityScheme class."""
self.security_scheme_type = security_scheme_type
self.description = description
self.name = name
self.in_ = in_
self.scheme = scheme
self.bearer_format = bearer_format
self.flows = flows
self.open_id_connect_url = open_id_connect_url
@@ -0,0 +1,19 @@
# Copyright (c) Microsoft. All rights reserved.
from urllib.parse import urlparse
from semantic_kernel.utils.feature_stage_decorator import experimental
@experimental
class Uri:
"""The Uri class that represents the URI."""
def __init__(self, uri):
"""Initialize the Uri."""
self.uri = uri
def get_left_part(self):
"""Get the left part of the URI."""
parsed_uri = urlparse(self.uri)
return f"{parsed_uri.scheme}://{parsed_uri.netloc}"