Skip to content
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

Feature/generator reduction #219

Merged
merged 17 commits into from
Feb 6, 2024
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.2.0] - 2024-01-31

### Added
- Added methods in request information to reduce the amount of code being generated.

## [1.1.0] - 2024-01-25

### Added
Expand Down
2 changes: 1 addition & 1 deletion kiota_abstractions/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VERSION: str = "1.1.0"
VERSION: str = "1.2.0"
18 changes: 15 additions & 3 deletions kiota_abstractions/base_request_configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,31 @@
# See License in the project root for license information.
# ------------------------------------
from dataclasses import dataclass
from typing import Dict, List, Optional, Union
from typing import Generic, List, Optional, TypeVar
from warnings import warn

from .headers_collection import HeadersCollection
from .request_option import RequestOption
baywet marked this conversation as resolved.
Show resolved Hide resolved

QueryParameters = TypeVar('QueryParameters')


@dataclass
class BaseRequestConfiguration:
class RequestConfiguration(Generic[QueryParameters]):
"""
Configuration for the request such as headers, query parameters, and middleware options.
"""
# Request headers
headers: HeadersCollection = HeadersCollection()

# Request options
options: Optional[List[RequestOption]] = None
# Request query parameters
query_parameters: Optional[QueryParameters] = None


@dataclass
class BaseRequestConfiguration(RequestConfiguration):
warn(
"BaseRequestConfiguration is deprecated. Use RequestConfiguration class instead.",
DeprecationWarning
)
12 changes: 11 additions & 1 deletion kiota_abstractions/default_query_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,20 @@
# See License in the project root for license information.
# ------------------------------------
from dataclasses import dataclass
from typing import List, Optional
from warnings import warn


@dataclass
class GetQueryParameters:
class QueryParameters:
samwelkanda marked this conversation as resolved.
Show resolved Hide resolved
"""
Default placeholder class for query parameters.
"""


@dataclass
class GetQueryParameters(QueryParameters):
"""
Default placeholder class for query parameters.
"""
warn("GetQueryParameters is deprecated. Use QueryParameters instead.", DeprecationWarning)
53 changes: 39 additions & 14 deletions kiota_abstractions/request_information.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from stduritemplate import StdUriTemplate

from ._version import VERSION
from .base_request_configuration import RequestConfiguration
from .headers_collection import HeadersCollection
from .method import Method
from .request_option import RequestOption
Expand All @@ -19,15 +20,11 @@

Url = str
T = TypeVar("T", bound=Parsable)
QueryParameters = TypeVar('QueryParameters')
OBSERVABILITY_TRACER_NAME = "microsoft-python-kiota-abstractions"
tracer = trace.get_tracer(OBSERVABILITY_TRACER_NAME, VERSION)


@dataclass
class QueryParams:
pass


class RequestInformation:
"""This class represents an abstract HTTP request"""

Expand All @@ -36,30 +33,56 @@ class RequestInformation:
CONTENT_TYPE_HEADER = "Content-Type"
REQUEST_TYPE_KEY = "com.microsoft.kiota.request.type"

def __init__(self) -> None:
def __init__(
self,
method: Optional[Method] = None,
url_template: Optional[str] = None,
path_parameters: Dict[str, Any] = {}
) -> None:
"""Creates a new instance of the RequestInformation class.

Args:
method (Method): The request method.
url_template (str): The given url template.
path_parameters (Dict[str, Any], optional): Path parameters
for the request. Defaults to {}.
"""
# The uri of the request
self.__uri: Optional[Url] = None

self.__request_options: Dict[str, RequestOption] = {}

# The path parameters for the current request
self.path_parameters: Dict[str, Any] = {}
self.path_parameters: Dict[str, Any] = path_parameters

# The URL template for the request
self.url_template: Optional[str] = None
self.url_template: Optional[str] = url_template

# The HTTP Method for the request
self.http_method: Optional[Method] = None
self.http_method: Optional[Method] = method

# The query parameters for the request
self.query_parameters: Dict[str, QueryParams] = {}
self.query_parameters: Dict[str, Any] = {}

# The Request Headers
self.headers: HeadersCollection = HeadersCollection()

# The Request Body
self.content: Optional[BytesIO] = None

def configure(self, request_configuration: RequestConfiguration) -> None:
"""Configures the current request information headers, query parameters, and options
based on the request configuration provided

Args:
request_configuration (RequestConfiguration): Configuration instance to
configure the request information.
"""
if request_configuration:
self.headers.add_all(request_configuration.headers)
self.add_request_options(request_configuration.options)
self.set_query_string_parameters_from_raw_object(request_configuration.query_parameters)

@property
def url(self) -> Url:
"""Gets the URL of the request"""
Expand Down Expand Up @@ -105,7 +128,7 @@ def request_options(self) -> Dict[str, RequestOption]:
"""Gets the request options for the request."""
return self.__request_options

def add_request_options(self, options: List[RequestOption]) -> None:
def add_request_options(self, options: Optional[List[RequestOption]]) -> None:
if not options:
return
for option in options:
Expand Down Expand Up @@ -202,15 +225,17 @@ def set_stream_content(self, value: BytesIO, content_type: Optional[str] = None)
self.headers.try_add(self.CONTENT_TYPE_HEADER, content_type)
self.content = value

def set_query_string_parameters_from_raw_object(self, q: Optional[QueryParams]) -> None:
def set_query_string_parameters_from_raw_object(self, q: Optional[QueryParameters]) -> None:
if q:
for field in fields(q):
for field in fields(q): # type: ignore
key = field.name
if hasattr(q, "get_query_parameter"):
serialization_key = q.get_query_parameter(key) # type: ignore
if serialization_key:
key = serialization_key
self.query_parameters[key] = getattr(q, field.name)
value = getattr(q, field.name)
if value is not None:
self.query_parameters[key] = value

def _get_serialization_writer(
self,
Expand Down
1 change: 1 addition & 0 deletions kiota_abstractions/serialization/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .additional_data_holder import AdditionalDataHolder
from .composed_type_wrapper import ComposedTypeWrapper
from .parsable import Parsable
from .parsable_factory import ParsableFactory
from .parse_node import ParseNode
Expand Down
44 changes: 44 additions & 0 deletions tests/test_request_information.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import pytest
from dataclasses import dataclass
from typing import Optional

from kiota_abstractions.request_information import RequestInformation
from kiota_abstractions.headers_collection import HeadersCollection
from kiota_abstractions.base_request_configuration import RequestConfiguration


def test_initialization():
Expand Down Expand Up @@ -83,3 +86,44 @@ def test_set_stream_content(mock_request_information):
mock_request_information.set_stream_content(b'stream')
assert mock_request_information.content == b'stream'
assert mock_request_information.headers.get("content-type") == {"application/octet-stream"}

def test_configure_empty_configuration(mock_request_information):
"""Tests configuring the request information
"""
request_config = RequestConfiguration()
mock_request_information.configure(request_config)
assert not mock_request_information.headers.get_all()
assert not mock_request_information.request_options
assert not mock_request_information.query_parameters

def test_configure_request_configuration(mock_request_information):
"""Tests configuring the request information
"""

@dataclass
class CustomParams:
filter: Optional[str] = None

def get_query_parameter(self,original_name: Optional[str] = None) -> str:
"""
Maps the query parameters names to their encoded names for the URI template parsing.
param original_name: The original query parameter name in the class.
Returns: str
"""
if not original_name:
raise TypeError("original_name cannot be null.")
if original_name == "filter":
return "%24filter"

query_params = CustomParams(filter="query1")
headers = HeadersCollection()
headers.add("header1", "value1")
headers.add("header2", "value2")

request_config = RequestConfiguration(headers=headers, query_parameters=query_params)

mock_request_information.configure(request_config)
assert mock_request_information.headers.get("header1") == {"value1"}
assert mock_request_information.headers.get("header2") == {"value2"}
assert mock_request_information.query_parameters == {"%24filter": "query1"}
assert not mock_request_information.request_options
Loading