Skip to content

[Core] Create generic azure-core package: corehttp #32191

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 2 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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: 3 additions & 2 deletions .vscode/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"sdk/core/azure-core-tracing-opencensus/**",
"sdk/core/azure-core-tracing-opentelemetry/**",
"sdk/core/azure-servicemanagement-legacy/**",
"sdk/core/corehttp/**",
"sdk/digitaltwins/azure-digitaltwins-core/**",
"sdk/eventhub/azure-eventhub-checkpointstoretable/**",
"sdk/eventhub/azure-eventhub-checkpointstoreblob-aio/**",
Expand Down Expand Up @@ -99,7 +100,7 @@
"sdk/translation/azure-ai-translation-text/tests/test_transliteration.py",
"sdk/translation/azure-ai-translation-text/tests/test_break_sentence_async.py",
"sdk/translation/azure-ai-translation-text/tests/test_translation_async.py",
"sdk/translation/azure-ai-translation-text/tests/test_transliteration_async.py",
"sdk/translation/azure-ai-translation-text/tests/test_transliteration_async.py",
"sdk/translation/test-resources.json",
"eng/**/*.json",
"eng/*.txt",
Expand Down Expand Up @@ -502,7 +503,7 @@
"words": [
"wammsa"
]
},
},
{
"filename": "sdk/tables/azure-data-tables/tests/**/*.py",
"words": [
Expand Down
3 changes: 3 additions & 0 deletions eng/.docsettings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ known_content_issues:
- ['sdk/appconfiguration/azure-appconfiguration/swagger/README.md', '#4554']
- ['sdk/attestation/azure-security-attestation/swagger/README.md', '#4554']
- ['sdk/core/azure-core/tests/testserver_tests/coretestserver/README.rst', '#4554']
- ['sdk/core/corehttp/tests/testserver_tests/coretestserver/README.rst', '#4554']
- ['sdk/media/azure-media-analytics-edge/README.md', '#4554']
- ['sdk/remoterendering/azure-mixedreality-remoterendering/README.md', '#4554']
- ['sdk/modelsrepository/azure-iot-modelsrepository/README.md', '#4554']
Expand All @@ -115,6 +116,8 @@ known_content_issues:
- ['sdk/core/azure-common/README.rst', 'common']
- ['sdk/core/azure-core/README.md', 'common']
- ['sdk/core/azure-core/samples/README.md', 'common']
- ['sdk/core/corehttp/README.md', 'common']
- ['sdk/core/corehttp/samples/README.md', 'common']
- ['sdk/search/azure-search-documents/README.md', 'common']
- ['sdk/storage/azure-storage-blob/samples/README.md', 'common']
- ['sdk/storage/azure-storage-file-datalake/samples/README.md', 'common']
Expand Down
5 changes: 4 additions & 1 deletion sdk/core/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ extends:
template: ../../eng/pipelines/templates/stages/archetype-sdk-client.yml
parameters:
ServiceDirectory: core
BuildTargetingString: '*'
ValidateFormatting: true
Artifacts:
- name: azure-core
Expand All @@ -49,4 +50,6 @@ extends:
safeName: azurecommon
skipPublishDocMs: true
- name: azure-core-experimental
safeName: azurecoreexperimental
safeName: azurecoreexperimental
- name: corehttp
safeName: corehttp
5 changes: 5 additions & 0 deletions sdk/core/corehttp/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Release History

## 1.0.0b1 (2023-10-18)

* Initial Release
21 changes: 21 additions & 0 deletions sdk/core/corehttp/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Copyright (c) Microsoft Corporation.

MIT License

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
6 changes: 6 additions & 0 deletions sdk/core/corehttp/MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
recursive-include tests *.py
include *.md
include LICENSE
include corehttp/__init__.py
recursive-include samples *.py *.md
include corehttp/py.typed
29 changes: 29 additions & 0 deletions sdk/core/corehttp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

# Core HTTP shared client library for Python

`corehttp` provides shared exceptions and modules for Python SDK client libraries.

## Getting started

Typically, you will not need to install `corehttp`, as it will be installed when you install one of the client libraries using it.

## Contributing

This project welcomes contributions and suggestions. Most contributions require
you to agree to a Contributor License Agreement (CLA) declaring that you have
the right to, and actually do, grant us the rights to use your contribution.
For details, visit [https://cla.microsoft.com](https://cla.microsoft.com).

When you submit a pull request, a CLA-bot will automatically determine whether
you need to provide a CLA and decorate the PR appropriately (e.g., label,
comment). Simply follow the instructions provided by the bot. You will only
need to do this once across all repos using our CLA.

This project has adopted the
[Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information, see the
[Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
or contact [[email protected]](mailto:[email protected]) with any
additional questions or comments.


35 changes: 35 additions & 0 deletions sdk/core/corehttp/corehttp/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# --------------------------------------------------------------------------
#
# Copyright (c) Microsoft Corporation. All rights reserved.
#
# The MIT License (MIT)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the ""Software""), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#
# --------------------------------------------------------------------------

from ._version import VERSION

__version__ = VERSION

from ._match_conditions import MatchConditions

__all__ = [
"MatchConditions",
]
46 changes: 46 additions & 0 deletions sdk/core/corehttp/corehttp/_match_conditions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# --------------------------------------------------------------------------
#
# Copyright (c) Microsoft Corporation. All rights reserved.
#
# The MIT License (MIT)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the ""Software""), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
#
# --------------------------------------------------------------------------

from enum import Enum


class MatchConditions(Enum):
"""An enum to describe match conditions."""

Unconditionally = 1
"""Matches any condition"""

IfNotModified = 2
"""If the target object is not modified. Usually it maps to etag=<specific etag>"""

IfModified = 3
"""Only if the target object is modified. Usually it maps to etag!=<specific etag>"""

IfPresent = 4
"""If the target object exists. Usually it maps to etag='*'"""

IfMissing = 5
"""If the target object does not exist. Usually it maps to etag!='*'"""
12 changes: 12 additions & 0 deletions sdk/core/corehttp/corehttp/_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# coding=utf-8
# --------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for
# license information.
#
# Code generated by Microsoft (R) AutoRest Code Generator.
# Changes may cause incorrect behavior and will be lost if the code is
# regenerated.
# --------------------------------------------------------------------------

VERSION = "1.0.0b1"
155 changes: 155 additions & 0 deletions sdk/core/corehttp/corehttp/credentials.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# -------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See LICENSE.txt in the project root for
# license information.
# -------------------------------------------------------------------------
from __future__ import annotations
from collections import namedtuple
from types import TracebackType
from typing import Any, NamedTuple, Optional, AsyncContextManager, Type
from typing_extensions import Protocol, runtime_checkable


class AccessToken(NamedTuple):
"""Represents an OAuth access token."""

token: str
expires_on: int


AccessToken.token.__doc__ = """The token string."""
AccessToken.expires_on.__doc__ = """The token's expiration time in Unix time."""


@runtime_checkable
class TokenCredential(Protocol):
"""Protocol for classes able to provide OAuth tokens."""

def get_token(self, *scopes: str, claims: Optional[str] = None, **kwargs: Any) -> AccessToken:
"""Request an access token for `scopes`.

:param str scopes: The type of access needed.

:keyword str claims: Additional claims required in the token, such as those returned in a resource
provider's claims challenge following an authorization failure.


:rtype: AccessToken
:return: An AccessToken instance containing the token string and its expiration time in Unix time.
"""
...


ServiceNamedKey = namedtuple("ServiceNamedKey", ["name", "key"])

__all__ = [
"AccessToken",
"ServiceKeyCredential",
"ServiceNamedKeyCredential",
"TokenCredential",
"AsyncTokenCredential",
]


class ServiceKeyCredential:
"""Credential type used for authenticating to a service.
It provides the ability to update the key without creating a new client.

:param str key: The key used to authenticate to a service
:raises: TypeError
"""

def __init__(self, key: str) -> None:
if not isinstance(key, str):
raise TypeError("key must be a string.")
self._key = key

@property
def key(self) -> str:
"""The value of the configured key.

:rtype: str
:return: The value of the configured key.
"""
return self._key

def update(self, key: str) -> None:
"""Update the key.

This can be used when you've regenerated your service key and want
to update long-lived clients.

:param str key: The key used to authenticate to a service
:raises: ValueError or TypeError
"""
if not key:
raise ValueError("The key used for updating can not be None or empty")
if not isinstance(key, str):
raise TypeError("The key used for updating must be a string.")
self._key = key


class ServiceNamedKeyCredential:
"""Credential type used for working with any service needing a named key that follows patterns
established by the other credential types.

:param str name: The name of the credential used to authenticate to a service.
:param str key: The key used to authenticate to a service.
:raises: TypeError
"""

def __init__(self, name: str, key: str) -> None:
if not isinstance(name, str) or not isinstance(key, str):
raise TypeError("Both name and key must be strings.")
self._credential = ServiceNamedKey(name, key)

@property
def named_key(self) -> ServiceNamedKey:
"""The value of the configured name.

:rtype: ServiceNamedKey
:return: The value of the configured name.
"""
return self._credential

def update(self, name: str, key: str) -> None:
"""Update the named key credential.

Both name and key must be provided in order to update the named key credential.
Individual attributes cannot be updated.

:param str name: The name of the credential used to authenticate to a service.
:param str key: The key used to authenticate to a service.
"""
if not isinstance(name, str) or not isinstance(key, str):
raise TypeError("Both name and key must be strings.")
self._credential = ServiceNamedKey(name, key)


@runtime_checkable
class AsyncTokenCredential(Protocol, AsyncContextManager["AsyncTokenCredential"]):
"""Protocol for classes able to provide OAuth tokens."""

async def get_token(self, *scopes: str, claims: Optional[str] = None, **kwargs: Any) -> AccessToken:
"""Request an access token for `scopes`.

:param str scopes: The type of access needed.

:keyword str claims: Additional claims required in the token, such as those returned in a resource
provider's claims challenge following an authorization failure.

:rtype: AccessToken
:return: An AccessToken instance containing the token string and its expiration time in Unix time.
"""
...

async def close(self) -> None:
pass

async def __aexit__(
self,
exc_type: Optional[Type[BaseException]] = None,
exc_value: Optional[BaseException] = None,
traceback: Optional[TracebackType] = None,
) -> None:
pass
Loading