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

Task/end to end testing #1761

Merged
merged 29 commits into from
Aug 16, 2022
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
a25177a
Fix method to set authorization header
samwelkanda Jul 15, 2022
8bbb185
Change additional data into a property
samwelkanda Jul 15, 2022
21b31f7
Rename method to create from discriminator value
samwelkanda Jul 15, 2022
c22bd29
Rename methods to be consistent with generated names
samwelkanda Jul 15, 2022
ccf1ae0
Rename serializarion writer to be consistent with generated names
samwelkanda Jul 15, 2022
e1decc9
Update request information to fix failing requests
samwelkanda Jul 15, 2022
f7311dc
Fix code issues with abstractions
samwelkanda Jul 22, 2022
47b8d01
Update request options to be optional parameter
samwelkanda Jul 22, 2022
ef19819
Merge branch 'main' into task/end-to-end-testing
samwelkanda Jul 22, 2022
4e9b9ef
Fix issues with http library
samwelkanda Jul 22, 2022
dd36577
Update dependencies across the libraries
samwelkanda Jul 22, 2022
ab509cb
Update json parse node with correct method names
samwelkanda Jul 22, 2022
ea0744c
update parse node factory to work with content as python dict
samwelkanda Jul 22, 2022
a6e697f
Clean up json serialization writer
samwelkanda Jul 22, 2022
06af9cb
Fix issues from code checks
samwelkanda Jul 22, 2022
9a1743a
Fix failing serialization tests
samwelkanda Jul 26, 2022
aea7e87
Add tests for azure authentication library
samwelkanda Jul 27, 2022
37dcdbe
Remove unused imports
samwelkanda Jul 27, 2022
1ed282b
Update and fix failing http tests
samwelkanda Jul 29, 2022
4a9ad39
Merge branch 'main' into task/end-to-end-testing
samwelkanda Aug 1, 2022
e650d7f
Update package versions
samwelkanda Aug 1, 2022
b7e0471
Add an entry to the changelog
samwelkanda Aug 1, 2022
fe4685c
Remove commented code
samwelkanda Aug 4, 2022
42cbcc3
Rename method to get bytes value
samwelkanda Aug 4, 2022
2a0eadc
Fix issue with instantiating serializer and deserializer
samwelkanda Aug 4, 2022
699ff08
Remove self reference in static method getpathparameters
samwelkanda Aug 4, 2022
7fcd361
Merge branch 'main' into task/end-to-end-testing
samwelkanda Aug 4, 2022
6cdb365
- fixes error message in defensive programing
baywet Aug 12, 2022
3f01bdd
Merge branch 'main' into task/end-to-end-testing
baywet Aug 12, 2022
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
4 changes: 4 additions & 0 deletions .github/workflows/authentication-python-azure.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ jobs:
run: |
pipenv run mypy authentication_azure
working-directory: ${{ env.relativePath }}
- name: Run tests with Pytest
run: |
pipenv run pytest
working-directory: ${{ env.relativePath }}

publish:
name: Publish distribution to PyPI
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
- Updated test suite and tooling for python abstractions and core packages. [#1761](https://github.com/microsoft/kiota/issues/367)
- Added support for no-content responses in python abstractions and http packages. [#1630](https://github.com/microsoft/kiota/issues/1459)
- Added support for vendor-specific content types in python. [#1631](https://github.com/microsoft/kiota/issues/1463)
- Simplified field deserializers for json in Python. [#1632](https://github.com/microsoft/kiota/issues/1492)
Expand Down
2 changes: 1 addition & 1 deletion abstractions/python/kiota/abstractions/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VERSION: str = '0.4.0'
VERSION: str = '0.5.0'
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,18 @@ def register_default_serializer(factory_class: SerializationWriterFactory) -> No
Args:
factory_class (SerializationWriterFactory):the class of the factory to be registered.
"""
base_class = type(factory_class)
serializer = base_class()
serializer = factory_class()
SerializationWriterFactoryRegistry().CONTENT_TYPE_ASSOCIATED_FACTORIES[
serializer.get_valid_content_type()] = serializer


def register_default_deserializer(self, factory_class: ParseNodeFactory) -> None:
def register_default_deserializer(factory_class: ParseNodeFactory) -> None:
"""Registers the default deserializer to the registry.

Args:
factory_class (ParseNodeFactory):the class of the factory to be registered.
"""
base_class = type(factory_class)
deserializer = base_class()
deserializer = factory_class()
ParseNodeFactoryRegistry().CONTENT_TYPE_ASSOCIATED_FACTORIES[
deserializer.get_valid_content_type()] = deserializer

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ def __init__(self, allowed_hosts: List[str]) -> None:
allowed_hosts (List[str]): A list of valid hosts. If the list is empty, all hosts
are valid.
"""
if not isinstance(allowed_hosts, list):
raise TypeError("Allowed hosts must be a list of strings")

self.allowed_hosts: Set[str] = {x.lower() for x in allowed_hosts}

def get_allowed_hosts(self) -> List[str]:
Expand All @@ -31,6 +34,8 @@ def set_allowed_hosts(self, allowed_hosts: List[str]) -> None:
allowed_hosts (List[str]): A list of valid hosts. If the list is empty, all hosts
are valid
"""
if not isinstance(allowed_hosts, list):
raise TypeError("Allowed hosts must be a list of strings")
self.allowed_hosts = {x.lower() for x in allowed_hosts}

def is_url_host_valid(self, url: str) -> bool:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ async def authenticate_request(self, request: RequestInformation) -> None:
"""
if not request:
raise Exception("Request cannot be null")
if not request.get_request_headers():
if not request.request_headers:
request.headers = {}

if not self.AUTHORIZATION_HEADER in request.headers:
token = await self.access_token_provider.get_authorization_token(request.get_url())
token = await self.access_token_provider.get_authorization_token(request.url)
if token:
request.add_request_headers({f'{self.AUTHORIZATION_HEADER}': f'Bearer {token}'})
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from .request_information import RequestInformation


def get_path_parameters(self, parameters: Union[Dict[str, Any], Optional[str]]) -> Dict[str, Any]:
def get_path_parameters(parameters: Union[Dict[str, Any], Optional[str]]) -> Dict[str, Any]:
result: Dict[str, Any] = {}
if isinstance(parameters, str):
result[RequestInformation.RAW_URL_KEY] = parameters
Expand Down
4 changes: 1 addition & 3 deletions abstractions/python/kiota/abstractions/method.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@


class Method(Enum):
"""
Represents the HTTP method used by a request.
"""
"""Represents the HTTP method used by a request."""
# The HTTP GET method
GET = "GET"
# The HTTP POST method
Expand Down
77 changes: 50 additions & 27 deletions abstractions/python/kiota/abstractions/request_information.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from dataclasses import fields
from io import BytesIO
from typing import TYPE_CHECKING, Any, Dict, Generic, List, Optional, Tuple, TypeVar
from typing import TYPE_CHECKING, Any, Dict, Generic, List, Optional, Tuple, TypeVar, Union

from uritemplate import URITemplate

from .method import Method
from .request_option import RequestOption
from .serialization import Parsable
from .serialization import Parsable, SerializationWriter

if TYPE_CHECKING:
from .request_adapter import RequestAdapter
Expand Down Expand Up @@ -34,10 +34,10 @@ def __init__(self) -> None:
self.path_parameters: Dict[str, Any] = {}

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

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

# The query parameters for the request
self.query_parameters: Dict[str, QueryParams] = {}
Expand All @@ -46,19 +46,20 @@ def __init__(self) -> None:
self.headers: Dict[str, str] = {}

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

def get_url(self) -> Url:
@property
def url(self) -> Url:
""" Gets the URL of the request
"""
raw_url = self.path_parameters.get(self.RAW_URL_KEY)
if self.__uri:
return self.__uri
if raw_url:
return raw_url
if not self.query_parameters:
if self.query_parameters is None:
raise Exception("Query parameters cannot be null")
if not self.path_parameters:
if self.path_parameters is None:
raise Exception("Path parameters cannot be null")
if not self.url_template:
raise Exception("Url Template cannot be null")
Expand All @@ -73,7 +74,8 @@ def get_url(self) -> Url:
result = template.expand(data)
return result

def set_url(self, url: Url) -> None:
@url.setter
def url(self, url: Url) -> None:
""" Sets the URL of the request
"""
if not url:
Expand All @@ -82,7 +84,8 @@ def set_url(self, url: Url) -> None:
self.query_parameters.clear()
self.path_parameters.clear()

def get_request_headers(self) -> Optional[Dict]:
@property
def request_headers(self) -> Optional[Dict]:
return self.headers

def add_request_headers(self, headers_to_add: Optional[Dict[str, str]]) -> None:
Expand All @@ -101,10 +104,11 @@ def remove_request_headers(self, key: str) -> None:
if key and key.lower() in self.headers:
del self.headers[key.lower()]

def get_request_options(self) -> List[Tuple[str, RequestOption]]:
@property
def request_options(self) -> Dict[str, RequestOption]:
"""Gets the request options for the request.
"""
return list(self.__request_options.items())
return self.__request_options

def add_request_options(self, options: List[RequestOption]) -> None:
if not options:
Expand All @@ -120,32 +124,24 @@ def remove_request_options(self, options: List[RequestOption]) -> None:

def set_content_from_parsable(
self, request_adapter: Optional['RequestAdapter'], content_type: Optional[str],
values: List[T]
values: Union[T, List[T]]
) -> None:
"""Sets the request body from a model with the specified content type.

Args:
request_adapter (Optional[RequestAdapter]): The adapter service to get the serialization
writer from.
content_type (Optional[str]): the content type.
values (List[T]): the models.
values (Union[T, List[T]]): the models.
"""
if not request_adapter:
raise Exception("HttpCore cannot be undefined")
if not content_type:
raise Exception("HttpCore cannot be undefined")
if not values:
raise Exception("Values cannot be empty")
writer = self._get_serialization_writer(request_adapter, content_type, values)

writer = request_adapter.get_serialization_writer_factory(
).get_serialization_writer(content_type)
self.headers[self.CONTENT_TYPE_HEADER] = content_type
if len(values) == 1:
writer.write_object_value(None, values[0])
if isinstance(values, list):
writer.writer = writer.write_collection_of_object_values(None, values)
else:
writer.write_collection_of_object_values(None, values)
writer.writer = writer.write_object_value(None, values)

self.content = writer.get_serialized_content()
self._set_content_and_content_type(writer, content_type)

def set_stream_content(self, value: BytesIO) -> None:
"""Sets the request body to be a binary stream.
Expand All @@ -165,3 +161,30 @@ def set_query_string_parameters_from_raw_object(self, q: Optional[QueryParams])
if serialization_key:
key = serialization_key
self.query_parameters[key] = getattr(q, field.name)

def _get_serialization_writer(
self, request_adapter: Optional['RequestAdapter'], content_type: Optional[str],
values: Union[T, List[T]]
):
"""_summary_

Args:
request_adapter (RequestAdapter): _description_
content_type (str): _description_
values (Union[T, List[T]]): _description_
"""
if not request_adapter:
raise Exception("HttpCore cannot be null")
if not content_type:
raise Exception("Content Type cannot be null")
if not values:
raise Exception("Values cannot be null")
return request_adapter.get_serialization_writer_factory(
).get_serialization_writer(content_type)

def _set_content_and_content_type(
self, writer: SerializationWriter, content_type: Optional[str]
):
if content_type:
self.headers[self.CONTENT_TYPE_HEADER] = content_type
self.content = writer.get_serialized_content()
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,12 @@ class AdditionalDataHolder(ABC):
"""Defines a contract for models that can hold additional data besides the described properties.
"""

@property
@abstractmethod
def get_additional_data(self) -> Dict[str, Any]:
def additional_data(self) -> Dict[str, Any]:
"""Stores the additional data for this object that did not belong to the properties.

Returns:
Dict[str, Any]: The additional data for this object
"""
pass

@abstractmethod
def set_additional_data(self, value):
pass
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class ParsableFactory(Parsable):
"""

@staticmethod
def create(parse_node: Optional[ParseNode]) -> U:
def create_from_discriminator_value(parse_node: Optional[ParseNode]) -> U:
"""Create a new parsable object from the given serialized data.

Args:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class ParseNode(ABC):
"""

@abstractmethod
def get_string_value(self) -> str:
def get_str_value(self) -> str:
"""Gets the string value of the node

Returns:
Expand All @@ -47,7 +47,7 @@ def get_child_node(self, identifier: str) -> ParseNode:
pass

@abstractmethod
def get_boolean_value(self) -> Optional[bool]:
def get_bool_value(self) -> Optional[bool]:
"""Gets the boolean value of the node

Returns:
Expand Down Expand Up @@ -83,11 +83,11 @@ def get_uuid_value(self) -> Optional[UUID]:
pass

@abstractmethod
def get_datetime_offset_value(self) -> Optional[datetime]:
"""Gets the datetime offset value of the node
def get_datetime_value(self) -> Optional[datetime]:
"""Gets the datetime value of the node

Returns:
datetime: The datetime offset value of the node
datetime: The datetime value of the node
"""
pass

Expand Down Expand Up @@ -166,7 +166,7 @@ def get_object_value(self, factory: ParsableFactory) -> U:
pass

@abstractmethod
def get_byte_array_value(self) -> BytesIO:
def get_bytes_value(self) -> BytesIO:
"""Get a bytearray value from the nodes

Returns:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class SerializationWriter(ABC):
"""

@abstractmethod
def write_string_value(self, key: Optional[str], value: Optional[str]) -> None:
def write_str_value(self, key: Optional[str], value: Optional[str]) -> None:
"""Writes the specified string value to the stream with an optional given key.

Args:
Expand All @@ -28,7 +28,7 @@ def write_string_value(self, key: Optional[str], value: Optional[str]) -> None:
pass

@abstractmethod
def write_boolean_value(self, key: Optional[str], value: Optional[bool]) -> None:
def write_bool_value(self, key: Optional[str], value: Optional[bool]) -> None:
"""Writes the specified boolean value to the stream with an optional given key.

Args:
Expand Down Expand Up @@ -68,7 +68,7 @@ def write_uuid_value(self, key: Optional[str], value: Optional[UUID]) -> None:
pass

@abstractmethod
def write_datetime_offset_value(self, key: Optional[str], value: Optional[datetime]) -> None:
def write_datetime_value(self, key: Optional[str], value: Optional[datetime]) -> None:
"""Writes the specified datetime offset value to the stream with an optional given key.

Args:
Expand Down Expand Up @@ -146,7 +146,7 @@ def write_collection_of_enum_values(
pass

@abstractmethod
def write_bytearray_value(self, key: Optional[str], value: BytesIO) -> None:
def write_bytes_value(self, key: Optional[str], value: BytesIO) -> None:
"""Writes the specified byte array as a base64 string to the stream with an optional
given key.

Expand Down
Loading