From 398b50fbcaa421b1c719ceb8b8065cc7e6e75777 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Fri, 16 Sep 2022 12:17:41 -0700 Subject: [PATCH 01/27] add core experimental --- sdk/core/azure-core-experimental/CHANGELOG.md | 7 + sdk/core/azure-core-experimental/LICENSE | 21 ++ sdk/core/azure-core-experimental/MANIFEST.in | 8 + sdk/core/azure-core-experimental/README.md | 24 ++ .../azure-core-experimental/azure/__init__.py | 1 + .../azure/core/__init__.py | 1 + .../azure/core/experimental/__init__.py | 1 + .../azure/core/experimental/_version.py | 6 + .../azure/core/experimental/py.typed | 0 .../core/experimental/transport/__init__.py | 58 +++++ .../core/experimental/transport/_pyodide.py | 158 +++++++++++++ .../dev_requirements.txt | 3 + .../pyodide_integration/async_testing.py | 27 +++ .../samples/pyodide_integration/browser.py | 105 +++++++++ .../pyodide_integration/data/hello-world.gz | Bin 0 -> 44 bytes .../samples/pyodide_integration/example-env | 4 + .../samples/pyodide_integration/index.html | 89 ++++++++ .../samples/pyodide_integration/readme.md | 43 ++++ .../pyodide_integration/requirements.txt | 5 + .../sdk_packaging.toml | 2 + sdk/core/azure-core-experimental/setup.py | 66 ++++++ .../tests/test_pyodide_transport.py | 212 ++++++++++++++++++ 22 files changed, 841 insertions(+) create mode 100644 sdk/core/azure-core-experimental/CHANGELOG.md create mode 100644 sdk/core/azure-core-experimental/LICENSE create mode 100644 sdk/core/azure-core-experimental/MANIFEST.in create mode 100644 sdk/core/azure-core-experimental/README.md create mode 100644 sdk/core/azure-core-experimental/azure/__init__.py create mode 100644 sdk/core/azure-core-experimental/azure/core/__init__.py create mode 100644 sdk/core/azure-core-experimental/azure/core/experimental/__init__.py create mode 100644 sdk/core/azure-core-experimental/azure/core/experimental/_version.py create mode 100644 sdk/core/azure-core-experimental/azure/core/experimental/py.typed create mode 100644 sdk/core/azure-core-experimental/azure/core/experimental/transport/__init__.py create mode 100644 sdk/core/azure-core-experimental/azure/core/experimental/transport/_pyodide.py create mode 100644 sdk/core/azure-core-experimental/dev_requirements.txt create mode 100644 sdk/core/azure-core-experimental/samples/pyodide_integration/async_testing.py create mode 100644 sdk/core/azure-core-experimental/samples/pyodide_integration/browser.py create mode 100644 sdk/core/azure-core-experimental/samples/pyodide_integration/data/hello-world.gz create mode 100644 sdk/core/azure-core-experimental/samples/pyodide_integration/example-env create mode 100644 sdk/core/azure-core-experimental/samples/pyodide_integration/index.html create mode 100644 sdk/core/azure-core-experimental/samples/pyodide_integration/readme.md create mode 100644 sdk/core/azure-core-experimental/samples/pyodide_integration/requirements.txt create mode 100644 sdk/core/azure-core-experimental/sdk_packaging.toml create mode 100644 sdk/core/azure-core-experimental/setup.py create mode 100644 sdk/core/azure-core-experimental/tests/test_pyodide_transport.py diff --git a/sdk/core/azure-core-experimental/CHANGELOG.md b/sdk/core/azure-core-experimental/CHANGELOG.md new file mode 100644 index 000000000000..c117570c6fcb --- /dev/null +++ b/sdk/core/azure-core-experimental/CHANGELOG.md @@ -0,0 +1,7 @@ +# Release History + +## 1.0.0b1 (Unreleased) + +### Features Added + +- pyodide implementation of azure-core transport protocol diff --git a/sdk/core/azure-core-experimental/LICENSE b/sdk/core/azure-core-experimental/LICENSE new file mode 100644 index 000000000000..63447fd8bbbf --- /dev/null +++ b/sdk/core/azure-core-experimental/LICENSE @@ -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. \ No newline at end of file diff --git a/sdk/core/azure-core-experimental/MANIFEST.in b/sdk/core/azure-core-experimental/MANIFEST.in new file mode 100644 index 000000000000..de24585adca7 --- /dev/null +++ b/sdk/core/azure-core-experimental/MANIFEST.in @@ -0,0 +1,8 @@ +recursive-include tests *.py +include *.md +include LICENSE +include azure/__init__.py +include azure/core/__init__.py +include azure/core/experimental/__init__.py +include azure/core/experimental/transport/*.py +recursive-include samples *.py diff --git a/sdk/core/azure-core-experimental/README.md b/sdk/core/azure-core-experimental/README.md new file mode 100644 index 000000000000..29c16138dcd3 --- /dev/null +++ b/sdk/core/azure-core-experimental/README.md @@ -0,0 +1,24 @@ + +# Azure Core Experimental client library for Python + +Azure Core Experimental client library provides experimental features that are not ready for stable release. The main reason might be because the feature depends on some other packages that there is no stable version available yet. If its dependant package introduces breaking changes, the features maybe break. It is not recommended to use azure core experimental library in production environment. + +## Getting started + +Install the azure core experimental package with [pip](https://pypi.org/project/pip/): + +```bash +pip install azure-core-experimental --pre +``` + +## Features list + +- pyodide transport + +## 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. + +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 [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. diff --git a/sdk/core/azure-core-experimental/azure/__init__.py b/sdk/core/azure-core-experimental/azure/__init__.py new file mode 100644 index 000000000000..0d1f7edf5dc6 --- /dev/null +++ b/sdk/core/azure-core-experimental/azure/__init__.py @@ -0,0 +1 @@ +__path__ = __import__('pkgutil').extend_path(__path__, __name__) # type: ignore diff --git a/sdk/core/azure-core-experimental/azure/core/__init__.py b/sdk/core/azure-core-experimental/azure/core/__init__.py new file mode 100644 index 000000000000..0d1f7edf5dc6 --- /dev/null +++ b/sdk/core/azure-core-experimental/azure/core/__init__.py @@ -0,0 +1 @@ +__path__ = __import__('pkgutil').extend_path(__path__, __name__) # type: ignore diff --git a/sdk/core/azure-core-experimental/azure/core/experimental/__init__.py b/sdk/core/azure-core-experimental/azure/core/experimental/__init__.py new file mode 100644 index 000000000000..0d1f7edf5dc6 --- /dev/null +++ b/sdk/core/azure-core-experimental/azure/core/experimental/__init__.py @@ -0,0 +1 @@ +__path__ = __import__('pkgutil').extend_path(__path__, __name__) # type: ignore diff --git a/sdk/core/azure-core-experimental/azure/core/experimental/_version.py b/sdk/core/azure-core-experimental/azure/core/experimental/_version.py new file mode 100644 index 000000000000..ac9f392f513e --- /dev/null +++ b/sdk/core/azure-core-experimental/azure/core/experimental/_version.py @@ -0,0 +1,6 @@ +# ------------------------------------ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +# ------------------------------------ + +VERSION = "1.0.0b1" diff --git a/sdk/core/azure-core-experimental/azure/core/experimental/py.typed b/sdk/core/azure-core-experimental/azure/core/experimental/py.typed new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/sdk/core/azure-core-experimental/azure/core/experimental/transport/__init__.py b/sdk/core/azure-core-experimental/azure/core/experimental/transport/__init__.py new file mode 100644 index 000000000000..4a61fcca93fe --- /dev/null +++ b/sdk/core/azure-core-experimental/azure/core/experimental/transport/__init__.py @@ -0,0 +1,58 @@ +# -------------------------------------------------------------------------- +# +# 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. +# +# -------------------------------------------------------------------------- + +__all__ = [ + 'PyodideTransport', + 'PyodideTransportResponse', + 'PyodideStreamDownloadGenerator', +] + +def __dir__(): + return __all__ + +def __getattr__(name): + transport = None + if name == 'PyodideTransport': + try: + from ._pyodide import PyodideTransport + transport = PyodideTransport + except ImportError: + raise ImportError("pyodide package is not installed") + if name == 'PyodideTransportResponse': + try: + from ._pyodide import PyodideTransportResponse + transport = PyodideTransportResponse + except ImportError: + raise ImportError("pyodide package is not installed") + if name == 'PyodideStreamDownloadGenerator': + try: + from ._pyodide import PyodideStreamDownloadGenerator + transport = PyodideStreamDownloadGenerator + except ImportError: + raise ImportError("pyodide package is not installed") + if transport: + return transport + raise AttributeError(f"module 'azure.core.experimental.transport' has no attribute {name}") diff --git a/sdk/core/azure-core-experimental/azure/core/experimental/transport/_pyodide.py b/sdk/core/azure-core-experimental/azure/core/experimental/transport/_pyodide.py new file mode 100644 index 000000000000..11c8c4ff4102 --- /dev/null +++ b/sdk/core/azure-core-experimental/azure/core/experimental/transport/_pyodide.py @@ -0,0 +1,158 @@ +# -------------------------------------------------------------------------- +# +# 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 collections.abc import AsyncIterator +from io import BytesIO + +import js # pylint: disable=import-error +from pyodide import JsException # pylint: disable=import-error +from pyodide.http import pyfetch # pylint: disable=import-error + +from azure.core.exceptions import HttpResponseError +from azure.core.pipeline import Pipeline +from azure.core.utils import CaseInsensitiveDict + +from azure.core.rest._http_response_impl_async import AsyncHttpResponseImpl +from azure.core.pipeline.transport import HttpRequest, AsyncioRequestsTransport + + +class PyodideTransportResponse(AsyncHttpResponseImpl): + """Async response object for the `PyodideTransport`.""" + + @property + def js_stream(self): + """So we get a fresh stream every time.""" + return self._internal_response.clone().js_response.body + + async def close(self) -> None: + """We don't actually have control over closing connections in the browser, so we just pretend + to close. + """ + self._is_closed = True + + def body(self) -> bytes: + """The body is just the content.""" + return self.content + + async def load_body(self) -> None: + """Backcompat""" + if self._content is None: + self._content = await self._internal_response.clone().bytes() + +class PyodideStreamDownloadGenerator(AsyncIterator): + """Simple stream download generator that returns the contents of + a request. + """ + + # pylint: disable=unused-argument + def __init__(self, pipeline: Pipeline, response: PyodideTransportResponse, *_, **kwargs): + self._block_size = response._block_size + self.response = response + # use this to efficiently store bytes. + if kwargs.pop("decompress", False) and self.response.headers.get("enc", None) in ("gzip", "deflate"): + self._js_reader = response.js_stream.pipeThrough(js.DecompressionStream.new("gzip")).getReader() + else: + self._js_reader = response.js_stream.getReader() + self._stream = BytesIO() + + self._closed = False + # We cannot control how many bytes we get from `response.reader`. `self._buffer_left` + # indicates how many unread bytes there are in `self.stream` + self._buffer_left = 0 + self.done = False + + async def __anext__(self) -> bytes: + """Get the next block of bytes.""" + if self._closed: + raise StopAsyncIteration() + + # remember the initial stream position + start_pos = self._stream.tell() + # move stream position to the end + self._stream.read() + # read from reader until there is no more data or we have `self._block_size` unread bytes. + while self._buffer_left < self._block_size: + read = await self._js_reader.read() + if read.done: + self._closed = True + break + self._buffer_left += self._stream.write(bytes(read.value)) + + # move the stream position back to where we started + self._stream.seek(start_pos) + self._buffer_left -= self._block_size + return self._stream.read(self._block_size) + +class PyodideTransport(AsyncioRequestsTransport): + """**This object is experimental**, meaning it may be changed in a future release + or might break with a future Pyodide release. This transport was built with Pyodide + version 0.20.0. + + Implements a basic HTTP sender using the Pyodide Javascript Fetch API. + """ + + async def send(self, request: HttpRequest, **kwargs) -> PyodideTransportResponse: + """Send request object according to configuration. + + :param request: The request object to be sent. + :type request: ~azure.core.pipeline.transport.HttpRequest + :return: An HTTPResponse object. + :rtype: PyodideResponseTransport + """ + stream_response = kwargs.pop("stream_response", False) + endpoint = request.url + request_headers = dict(request.headers) + init = { + "method": request.method, + "headers": request_headers, + "body": request.data, + "files": request.files, + "verify": kwargs.pop("connection_verify", self.connection_config.verify), + "cert": kwargs.pop("connection_cert", self.connection_config.cert), + "allow_redirects": False, + **kwargs, + } + + try: + response = await pyfetch(endpoint, **init) + except JsException as error: + raise HttpResponseError(error, error=error) + + headers = CaseInsensitiveDict(response.js_response.headers) + transport_response = PyodideTransportResponse( + request=request, + internal_response=response, + block_size=self.connection_config.data_block_size, + status_code=response.status, + reason=response.status_text, + content_type=headers.get("content-type"), + headers=headers, + stream_download_generator=PyodideStreamDownloadGenerator, + ) + if not stream_response: + await transport_response.load_body() + + return transport_response \ No newline at end of file diff --git a/sdk/core/azure-core-experimental/dev_requirements.txt b/sdk/core/azure-core-experimental/dev_requirements.txt new file mode 100644 index 000000000000..f9c8d2994225 --- /dev/null +++ b/sdk/core/azure-core-experimental/dev_requirements.txt @@ -0,0 +1,3 @@ +-e ../../../tools/azure-sdk-tools +../azure-core +-e ../../../tools/azure-devtools \ No newline at end of file diff --git a/sdk/core/azure-core-experimental/samples/pyodide_integration/async_testing.py b/sdk/core/azure-core-experimental/samples/pyodide_integration/async_testing.py new file mode 100644 index 000000000000..1e3eff2f9901 --- /dev/null +++ b/sdk/core/azure-core-experimental/samples/pyodide_integration/async_testing.py @@ -0,0 +1,27 @@ +import traceback +import sys + + +class AsyncTestSuite: + """Async test cases + Test must be asynchronous and follow the pattern `test*`. + """ + + async def run(self): + """Run the tests an print the results.""" + print("".join(("-" * 8, type(self).__name__, "-" * 8))) + for method_name in dir(self): + if not method_name.startswith("test"): + continue + print(method_name, end="... ") + try: + await getattr(self, method_name)() + except AssertionError: + print("FAIL") + traceback.print_exception(*sys.exc_info()) + except Exception: # pylint: disable=broad-except + print("ERROR") + traceback.print_exception(*sys.exc_info()) + else: + print("PASS") + print() diff --git a/sdk/core/azure-core-experimental/samples/pyodide_integration/browser.py b/sdk/core/azure-core-experimental/samples/pyodide_integration/browser.py new file mode 100644 index 000000000000..545738ae6abe --- /dev/null +++ b/sdk/core/azure-core-experimental/samples/pyodide_integration/browser.py @@ -0,0 +1,105 @@ +from unittest.mock import _patch_dict, patch +from uuid import uuid4 + +from azure.ai.textanalytics.aio import TextAnalyticsClient +from azure.core.credentials import AzureKeyCredential +from azure.core.pipeline.transport import HttpRequest +from azure.core.experimental.transport import PyodideTransport +from azure.storage.blob.aio import BlobClient, BlobServiceClient + +# pylint: disable=import-error +from async_testing import AsyncTestSuite + + +class PyodideTransportIntegrationTestSuite(AsyncTestSuite): + """Integration tests for the Pyodide transport.""" + + text_analytics_client: TextAnalyticsClient + blob_service_client: BlobServiceClient + + def __init__( + self, + text_analytics_key: str, + text_analytics_endpoint: str, + blob_service_key: str, + blob_service_endpoint: str, + ): + self.text_analytics_client = TextAnalyticsClient( + endpoint=text_analytics_endpoint, + credential=AzureKeyCredential(text_analytics_key), + transport=PyodideTransport(), + ) + self.blob_service_client = BlobServiceClient( + blob_service_endpoint, blob_service_key, transport=PyodideTransport() + ) + + async def test_decompress_generator(self): + """Test that we can decompress streams properly.""" + url = "data/hello-world.gz" + request = HttpRequest(method="GET", url=url) + transport = PyodideTransport() + response = await transport.send(request, stream_response=True) + response.headers["enc"] = "deflate" + data = b"".join([x async for x in response.iter_bytes()]) + assert data == b"hello world\n" + + response = await transport.send(request, stream_response=True) + data = b"".join([x async for x in response.iter_raw()]) + assert data != b"hello world\n" + + response = await transport.send(request, stream_response=True) + data = b"".join([x async for x in response.iter_bytes()]) + assert data != b"hello world\n" + + response = await transport.send(request, stream_response=True) + response.headers["enc"] = "deflate" + data = b"".join([x async for x in response.iter_bytes()]) + assert data == b"hello world\n" + + + async def test_sentiment_analysis(self): + """Test that sentiment analysis works.""" + results = await self.text_analytics_client.analyze_sentiment( + ["good great amazing"] + ) + assert len(results) == 1 + result = results[0] + assert result.sentiment == "positive" + assert result.confidence_scores.positive > 0.98 + assert result.confidence_scores.neutral < 0.02 + assert result.confidence_scores.negative < 0.02 + + async def test_storage(self): + """Test that we can upload and download from blob storage""" + account_name = uuid4().hex + container_client = await self.blob_service_client.create_container(account_name) + blob_name = uuid4().hex + blob_data = b"012345" + try: + assert await container_client.exists() + blob_client = container_client.get_blob_client(blob_name) + await blob_client.upload_blob(blob_data) + + # make a new client so we don't have cached data + blob_client = BlobClient( + account_url=self.blob_service_client.url, + container_name=container_client.container_name, + blob_name=blob_name, + credential=container_client.credential, + max_single_get_size=1, + max_chunk_get_size=1, + transport=PyodideTransport(), + ) + assert await blob_client.exists() + downloader = await blob_client.download_blob() + i = 0 + async for chunk in downloader.chunks(): + assert chunk == bytes(str(i), "utf-8") + i += 1 + assert i == len(blob_data) + + except Exception: + await container_client.delete_container() + raise + else: + await container_client.delete_container() diff --git a/sdk/core/azure-core-experimental/samples/pyodide_integration/data/hello-world.gz b/sdk/core/azure-core-experimental/samples/pyodide_integration/data/hello-world.gz new file mode 100644 index 0000000000000000000000000000000000000000..34336ab5dd953ee01a608522d648b83797414fc9 GIT binary patch literal 44 zcmb2|=HR&IdLxN}IU_YECttTbzbGe#;k3uulPAM9&g-A@e8|M0Yt6Bqhk=0s0CRN@ Ai~s-t literal 0 HcmV?d00001 diff --git a/sdk/core/azure-core-experimental/samples/pyodide_integration/example-env b/sdk/core/azure-core-experimental/samples/pyodide_integration/example-env new file mode 100644 index 000000000000..57f925f76d42 --- /dev/null +++ b/sdk/core/azure-core-experimental/samples/pyodide_integration/example-env @@ -0,0 +1,4 @@ +TEXT_ANALYTICS_KEY= +TEXT_ANALYTICS_ENDPOINT= +BLOB_SERVICE_KEY= +BLOB_SERVICE_ENDPOINT=https://.blob.core.windows.net diff --git a/sdk/core/azure-core-experimental/samples/pyodide_integration/index.html b/sdk/core/azure-core-experimental/samples/pyodide_integration/index.html new file mode 100644 index 000000000000..9391e05df16a --- /dev/null +++ b/sdk/core/azure-core-experimental/samples/pyodide_integration/index.html @@ -0,0 +1,89 @@ + + + + + + + + + + diff --git a/sdk/core/azure-core-experimental/samples/pyodide_integration/readme.md b/sdk/core/azure-core-experimental/samples/pyodide_integration/readme.md new file mode 100644 index 000000000000..939fecdfc05a --- /dev/null +++ b/sdk/core/azure-core-experimental/samples/pyodide_integration/readme.md @@ -0,0 +1,43 @@ +# Integration Testing + +## Running + +Once you have set up your Azure Resources and your `.env` file, navigate to the `/sdk/core/azure-core`. Make a wheel of core by running + +```bash +python setup.py bdist_wheel +``` + +and run + +```python +python -h http.server +``` + +to set up the test server. Then, from a Chromium-based browser such as Edge, go to [`http://localhost:8000/samples/pyodide_integration`](http://localhost:8000/samples/test_pyodide_integration) and the tests will be run in the browser. Dev tip: keep your browser's devtools open. If you make a change to the source code, remember to rebuild your wheel. Note that you might have to update `requirements.txt` depending on the version of `azure-core`. Just make sure the url to `azure-core` in `requirements.txt` matches that of the wheel in `../../dist/`. + +## Adding tests + +Add tests in `browser_test.py`. I couldn't get `pytest` or `unittest` to cooperate with me, so I made my own little async testing framework (`async_test.py`). If you are creating new files to test or new packages, update the `TEST_FILES` and `PACKAGES` variables in `index.html`, import the test case, and run it. + +## Sensitive values + +To run the tests, you need a `.env` folder in this directory with your sensitive values. +see `example-env`. You can then access the values as environment variables using `os.getenv`. You will +need to have your `textanalytics` key and endpoint as well as your Blob Storage key and url. + +## Dependencies + +All all packages listed in `requirements.txt` will be available in the testing environment. + +## Azure Resources + +You need your own Text Analytics and Blob Storage accounts to run these tests. Blob storage requirest some additional configuration to work. To set up Blob Storage, navigate to your storage client homepage and go to the `Resource Sharing (CORS)` tab. Create a rule with the following values + +| Allowed origins | Allowed methods | Allowed headers | Exposed headers | Max age | +|-----------------|-----------------|-----------------|-----------------|---------| +| `*` | All | `*` | See below | `3600` | + +For exposed headers, put + +> Server,Content-Range,ETag,Last-Modified,Accept-Ranges,x-ms-*,enc diff --git a/sdk/core/azure-core-experimental/samples/pyodide_integration/requirements.txt b/sdk/core/azure-core-experimental/samples/pyodide_integration/requirements.txt new file mode 100644 index 000000000000..97135659a4df --- /dev/null +++ b/sdk/core/azure-core-experimental/samples/pyodide_integration/requirements.txt @@ -0,0 +1,5 @@ +python-dotenv +http://localhost:8000/dist/azure_core-1.25.0-py3-none-any.whl +azure-ai-textanalytics +azure-storage-blob +azure-ai-formrecognizer diff --git a/sdk/core/azure-core-experimental/sdk_packaging.toml b/sdk/core/azure-core-experimental/sdk_packaging.toml new file mode 100644 index 000000000000..e7687fdae93b --- /dev/null +++ b/sdk/core/azure-core-experimental/sdk_packaging.toml @@ -0,0 +1,2 @@ +[packaging] +auto_update = false \ No newline at end of file diff --git a/sdk/core/azure-core-experimental/setup.py b/sdk/core/azure-core-experimental/setup.py new file mode 100644 index 000000000000..16a68a096ab4 --- /dev/null +++ b/sdk/core/azure-core-experimental/setup.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python + +#------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for +# license information. +#-------------------------------------------------------------------------- + +import re +import os.path +from io import open +from setuptools import find_packages, setup # type: ignore + +# Change the PACKAGE_NAME only to change folder and different name +PACKAGE_NAME = "azure-core-experimental" +PACKAGE_PPRINT_NAME = "Core Experimental" + +package_folder_path = "azure/core/experimental" + +# Version extraction inspired from 'requests' +with open(os.path.join(package_folder_path, '_version.py'), 'r') as fd: + version = re.search(r'^VERSION\s*=\s*[\'"]([^\'"]*)[\'"]', # type: ignore + fd.read(), re.MULTILINE).group(1) + +if not version: + raise RuntimeError('Cannot find version information') + +with open('README.md', encoding='utf-8') as f: + readme = f.read() +with open('CHANGELOG.md', encoding='utf-8') as f: + changelog = f.read() + +setup( + name=PACKAGE_NAME, + version=version, + description='Microsoft Azure {} Library for Python'.format(PACKAGE_PPRINT_NAME), + long_description=readme + '\n\n' + changelog, + long_description_content_type='text/markdown', + license='MIT License', + author='Microsoft Corporation', + author_email='azpysdkhelp@microsoft.com', + url='https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/core/azure-core-experimental', + classifiers=[ + "Development Status :: 4 - Beta", + 'Programming Language :: Python', + 'Programming Language :: Python :: 3 :: Only', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', + 'License :: OSI Approved :: MIT License', + ], + zip_safe=False, + packages=[ + 'azure.core.experimental', + ], + include_package_data=True, + package_data={ + 'pytyped': ['py.typed'], + }, + python_requires=">=3.7", + install_requires=[ + 'azure-core<2.0.0,>=1.20.0', + ], +) diff --git a/sdk/core/azure-core-experimental/tests/test_pyodide_transport.py b/sdk/core/azure-core-experimental/tests/test_pyodide_transport.py new file mode 100644 index 000000000000..fa8a25c91847 --- /dev/null +++ b/sdk/core/azure-core-experimental/tests/test_pyodide_transport.py @@ -0,0 +1,212 @@ +# -------------------------------------------------------------------------- +# +# 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. +# +# -------------------------------------------------------------------------- +"""Tests that mock the browser layer.""" +import asyncio +import sys +from typing import NamedTuple +from unittest import mock + +import pytest +from azure.core.exceptions import HttpResponseError +from azure.core.pipeline._base_async import AsyncPipeline +from azure.core.pipeline.policies._retry_async import AsyncRetryPolicy +from azure.core.rest import HttpRequest + +PLACEHOLDER_ENDPOINT = "https://my-resource-group.cognitiveservices.azure.com/" + + +class TestPyodideTransportClass: + """Unittest for the Pyodide transport.""" + + @pytest.fixture() + def mock_pyodide_module(self): + """Create a mock for the Pyodide module.""" + mock_pyodide_module = mock.Mock() + mock_pyodide_module.http.pyfetch = mock.Mock() + mock_pyodide_module.JsException = type("JsException", (Exception,), {}) + return mock_pyodide_module + + @pytest.fixture() + def mock_js_module(self): + """Mock the `js` module""" + return mock.Mock() + + @pytest.fixture() + def transport(self, mock_pyodide_module, mock_js_module): + """Add the mock Pyodide module to `sys.modules` and import our transport.""" + # Use patch so we don't clutter up the `sys.modules` namespace. + patch_dict = ( + ("pyodide", mock_pyodide_module), + ("pyodide.http", mock_pyodide_module.http), + ("js", mock_js_module), + ) + with mock.patch.dict(sys.modules, patch_dict): + import azure.core.experimental.transport + + yield azure.core.experimental.transport + + @pytest.fixture() + def pipeline(self, transport): + """Create a pipeline to test.""" + return AsyncPipeline(transport.PyodideTransport(), [AsyncRetryPolicy()]) + + @pytest.fixture() + def mock_pyfetch(self, mock_pyodide_module): + """Utility fixture for less typing.""" + return mock_pyodide_module.http.pyfetch + + def create_mock_response( + self, body: bytes, headers: dict, status: int, status_text: str + ) -> mock.Mock: + """Create a mock response object that mimics `pyodide.http.FetchResponse`""" + mock_response = mock.Mock() + mock_response.body = body + mock_response.js_response.headers = headers + mock_response.status = status + mock_response.status_text = status_text + bytes_promise = asyncio.Future() + bytes_promise.set_result(body) + mock_response.bytes = mock.Mock() + mock_response.bytes.return_value = bytes_promise + mock_response.clone.return_value = mock_response + + response_promise = asyncio.Future() + response_promise.set_result(mock_response) + return response_promise + + @pytest.mark.asyncio + async def test_successful_send(self, mock_pyfetch, mock_pyodide_module, pipeline): + """Test that a successful send returns the correct values.""" + # setup data + mock_pyfetch.reset_mock() + method = "POST" + headers = {"key": "value"} + data = b"data" + request = HttpRequest( + method=method, url=PLACEHOLDER_ENDPOINT, headers=headers, data=data + ) + response_body = b"0123" + response_headers = {"header": "value"} + response_status = 200 + response_text = "OK" + mock_response = self.create_mock_response( + body=response_body, + headers=response_headers, + status=response_status, + status_text=response_text, + ) + mock_pyodide_module.http.pyfetch.return_value = mock_response + response = (await pipeline.run(request=request)).http_response + # Check that the pipeline processed the data correctly. + await response.load_body() + assert response.body() == response_body + assert response.status_code == response_status + assert response.headers == response_headers + assert response.reason == response_text + + assert not response._is_closed + await response.close() + assert response._is_closed + + # Check that the call had the correct arguments. + mock_pyfetch.assert_called_once() + args = mock_pyfetch.call_args[0] + kwargs = mock_pyfetch.call_args[1] + assert len(args) == 1 + assert args[0] == PLACEHOLDER_ENDPOINT + assert kwargs["method"] == method + assert kwargs["body"] == data + assert not kwargs["allow_redirects"] + assert kwargs["headers"]["key"] == "value" + assert kwargs["headers"]["Content-Length"] == str(len(data)) + assert kwargs["verify"] + assert kwargs["cert"] is None + assert not kwargs["files"] + + # check that the js_stream property is cloning + num_clones = mock_pyfetch.clone.call_count + response.js_stream + assert mock_pyfetch.call_count == num_clones + 1 + + @pytest.mark.asyncio + async def test_unsuccessful_send(self, mock_pyfetch, mock_pyodide_module, pipeline): + """Test that the pipeline is failing correctly.""" + mock_pyfetch.reset_mock() + mock_pyfetch.side_effect = mock_pyodide_module.JsException + retry_total = 3 + request = HttpRequest(method="GET", url=PLACEHOLDER_ENDPOINT) + with pytest.raises(HttpResponseError): + await pipeline.run(request) + # 3 retries plus the original request. + assert mock_pyfetch.call_count == retry_total + 1 + + @pytest.mark.asyncio + async def test_download_generator(self, transport): + """Test that the download generator is working correctly.""" + + class ReaderReturn(NamedTuple): + value: bytes + done: bool + + response_mock = mock.Mock() + response_mock._block_size = 5 + response_mock._js_reader.read = mock.Mock() + read_promise = asyncio.Future() + read_promise.set_result(ReaderReturn(value=b"01", done=False)) + reader = mock.Mock() + reader.read.return_value = read_promise + response_mock.js_stream.getReader.return_value = reader + generator = transport.PyodideStreamDownloadGenerator(pipeline=None, response=response_mock) + + assert len(await generator.__anext__()) == response_mock._block_size + assert reader.read.call_count == 3 + assert len(await generator.__anext__()) == response_mock._block_size + # 5 because there is a leftover byte from the previous `__anext__` call. + assert reader.read.call_count == 5 + + read_promise = asyncio.Future() + read_promise.set_result(ReaderReturn(value=None, done=True)) + reader.read.return_value = read_promise + await generator.__anext__() + with pytest.raises(StopAsyncIteration): + await generator.__anext__() + + @pytest.mark.asyncio + async def test_download_generator_compress(self, transport, mock_js_module): + """Test that we are attempting to decompress data when passing the `decompress`.""" + response = mock.Mock() + response.headers = {"enc": "deflate"} + transport.PyodideStreamDownloadGenerator(pipeline=None, response=response, decompress=True) + mock_js_module.DecompressionStream.new.assert_called_once_with("gzip") + + def test_valid_import(self, transport): + """Test that we can import Pyodide classes from `azure.core.pipeline.transport` + Adding the transport fixture will mock the Pyodide modules in `sys.modules`. + """ + # Use patch so we don't clutter up the `sys.modules` namespace. + import azure.core.experimental.transport as transport + assert transport.PyodideTransport + assert transport.PyodideTransportResponse From 254b47206aa71d859c7f6d4ba7656160eadf4b7d Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Fri, 16 Sep 2022 15:48:09 -0700 Subject: [PATCH 02/27] update --- .vscode/cspell.json | 1 + shared_requirements.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/.vscode/cspell.json b/.vscode/cspell.json index e802842e0496..218b4bceb344 100644 --- a/.vscode/cspell.json +++ b/.vscode/cspell.json @@ -264,6 +264,7 @@ "PSECRET", "pyfuncitem", "pygobject", + "pyodide", "parameterizing", "pytyped", "pytz", diff --git a/shared_requirements.txt b/shared_requirements.txt index a6e160b38afa..c121ef7ce2a4 100644 --- a/shared_requirements.txt +++ b/shared_requirements.txt @@ -507,3 +507,4 @@ opentelemetry-sdk<2.0.0,>=1.5.0,!=1.10a0 #override azure-mgmt-redis azure-mgmt-core>=1.3.2,<2.0.0 #override azure-mgmt-resourcegraph azure-mgmt-core>=1.3.2,<2.0.0 #override azure-mgmt-resourcegraph msrest>=0.7.1 +#override azure-core-experimental azure-core<2.0.0,>=1.20.0 From f33fc6b48c710bdab5d1450909e9d40b95112b69 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Fri, 16 Sep 2022 15:49:34 -0700 Subject: [PATCH 03/27] update --- sdk/core/azure-core-experimental/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/core/azure-core-experimental/README.md b/sdk/core/azure-core-experimental/README.md index 29c16138dcd3..defd2b834f17 100644 --- a/sdk/core/azure-core-experimental/README.md +++ b/sdk/core/azure-core-experimental/README.md @@ -8,7 +8,7 @@ Azure Core Experimental client library provides experimental features that are n Install the azure core experimental package with [pip](https://pypi.org/project/pip/): ```bash -pip install azure-core-experimental --pre +pip install azure-core-experimental ``` ## Features list From 92fa9ffa7b364b7f67e9ccb35292db3e00a6643f Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Fri, 16 Sep 2022 17:08:46 -0700 Subject: [PATCH 04/27] update --- .vscode/cspell.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.vscode/cspell.json b/.vscode/cspell.json index 218b4bceb344..e583204b0953 100644 --- a/.vscode/cspell.json +++ b/.vscode/cspell.json @@ -233,6 +233,7 @@ "myfile", "nazsdk", "nbytes", + "nbsp", "noarch", "NOPERM", "northcentralus", @@ -262,6 +263,7 @@ "prevsnapshot", "pschema", "PSECRET", + "pyfetch", "pyfuncitem", "pygobject", "pyodide", From 82792431803790f3372aaa8ab01537c5422425fe Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Mon, 19 Sep 2022 09:10:09 -0700 Subject: [PATCH 05/27] fix typo --- .../samples/pyodide_integration/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/core/azure-core-experimental/samples/pyodide_integration/readme.md b/sdk/core/azure-core-experimental/samples/pyodide_integration/readme.md index 939fecdfc05a..5f7ba3adc055 100644 --- a/sdk/core/azure-core-experimental/samples/pyodide_integration/readme.md +++ b/sdk/core/azure-core-experimental/samples/pyodide_integration/readme.md @@ -32,7 +32,7 @@ All all packages listed in `requirements.txt` will be available in the testing e ## Azure Resources -You need your own Text Analytics and Blob Storage accounts to run these tests. Blob storage requirest some additional configuration to work. To set up Blob Storage, navigate to your storage client homepage and go to the `Resource Sharing (CORS)` tab. Create a rule with the following values +You need your own Text Analytics and Blob Storage accounts to run these tests. Blob storage requires some additional configuration to work. To set up Blob Storage, navigate to your storage client homepage and go to the `Resource Sharing (CORS)` tab. Create a rule with the following values | Allowed origins | Allowed methods | Allowed headers | Exposed headers | Max age | |-----------------|-----------------|-----------------|-----------------|---------| From 32aeb70046cf31926f48aa14c819f81ba0aa5735 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Mon, 19 Sep 2022 10:54:24 -0700 Subject: [PATCH 06/27] update --- .../azure/core/experimental/__init__.py | 3 ++- .../azure/core/experimental/transport/__init__.py | 2 ++ .../azure/core/experimental/transport/_pyodide.py | 2 +- sdk/core/azure-core-experimental/setup.py | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/sdk/core/azure-core-experimental/azure/core/experimental/__init__.py b/sdk/core/azure-core-experimental/azure/core/experimental/__init__.py index 0d1f7edf5dc6..35bb7b7a2fb1 100644 --- a/sdk/core/azure-core-experimental/azure/core/experimental/__init__.py +++ b/sdk/core/azure-core-experimental/azure/core/experimental/__init__.py @@ -1 +1,2 @@ -__path__ = __import__('pkgutil').extend_path(__path__, __name__) # type: ignore +from ._version import VERSION +__version__ = VERSION diff --git a/sdk/core/azure-core-experimental/azure/core/experimental/transport/__init__.py b/sdk/core/azure-core-experimental/azure/core/experimental/transport/__init__.py index 4a61fcca93fe..7e477c622eb2 100644 --- a/sdk/core/azure-core-experimental/azure/core/experimental/transport/__init__.py +++ b/sdk/core/azure-core-experimental/azure/core/experimental/transport/__init__.py @@ -24,6 +24,8 @@ # # -------------------------------------------------------------------------- +# pylint: disable=undefined-all-variable + __all__ = [ 'PyodideTransport', 'PyodideTransportResponse', diff --git a/sdk/core/azure-core-experimental/azure/core/experimental/transport/_pyodide.py b/sdk/core/azure-core-experimental/azure/core/experimental/transport/_pyodide.py index 11c8c4ff4102..f3e51cac5ecf 100644 --- a/sdk/core/azure-core-experimental/azure/core/experimental/transport/_pyodide.py +++ b/sdk/core/azure-core-experimental/azure/core/experimental/transport/_pyodide.py @@ -155,4 +155,4 @@ async def send(self, request: HttpRequest, **kwargs) -> PyodideTransportResponse if not stream_response: await transport_response.load_body() - return transport_response \ No newline at end of file + return transport_response diff --git a/sdk/core/azure-core-experimental/setup.py b/sdk/core/azure-core-experimental/setup.py index 16a68a096ab4..20ff9ceb5e1c 100644 --- a/sdk/core/azure-core-experimental/setup.py +++ b/sdk/core/azure-core-experimental/setup.py @@ -49,6 +49,7 @@ 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', + 'Programming Language :: Python :: 3.11', 'License :: OSI Approved :: MIT License', ], zip_safe=False, From 3cf9caad20a6bfbdb7680e579c00b812dbd8654f Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Mon, 19 Sep 2022 16:19:16 -0700 Subject: [PATCH 07/27] update --- .../core/experimental/transport/__init__.py | 19 +-------- .../tests/test_pyodide_transport.py | 40 ------------------- 2 files changed, 1 insertion(+), 58 deletions(-) diff --git a/sdk/core/azure-core-experimental/azure/core/experimental/transport/__init__.py b/sdk/core/azure-core-experimental/azure/core/experimental/transport/__init__.py index 7e477c622eb2..04aef882b0e0 100644 --- a/sdk/core/azure-core-experimental/azure/core/experimental/transport/__init__.py +++ b/sdk/core/azure-core-experimental/azure/core/experimental/transport/__init__.py @@ -28,33 +28,16 @@ __all__ = [ 'PyodideTransport', - 'PyodideTransportResponse', - 'PyodideStreamDownloadGenerator', ] def __dir__(): return __all__ def __getattr__(name): - transport = None if name == 'PyodideTransport': try: from ._pyodide import PyodideTransport - transport = PyodideTransport + return PyodideTransport except ImportError: raise ImportError("pyodide package is not installed") - if name == 'PyodideTransportResponse': - try: - from ._pyodide import PyodideTransportResponse - transport = PyodideTransportResponse - except ImportError: - raise ImportError("pyodide package is not installed") - if name == 'PyodideStreamDownloadGenerator': - try: - from ._pyodide import PyodideStreamDownloadGenerator - transport = PyodideStreamDownloadGenerator - except ImportError: - raise ImportError("pyodide package is not installed") - if transport: - return transport raise AttributeError(f"module 'azure.core.experimental.transport' has no attribute {name}") diff --git a/sdk/core/azure-core-experimental/tests/test_pyodide_transport.py b/sdk/core/azure-core-experimental/tests/test_pyodide_transport.py index fa8a25c91847..942f0a4da804 100644 --- a/sdk/core/azure-core-experimental/tests/test_pyodide_transport.py +++ b/sdk/core/azure-core-experimental/tests/test_pyodide_transport.py @@ -163,45 +163,6 @@ async def test_unsuccessful_send(self, mock_pyfetch, mock_pyodide_module, pipeli # 3 retries plus the original request. assert mock_pyfetch.call_count == retry_total + 1 - @pytest.mark.asyncio - async def test_download_generator(self, transport): - """Test that the download generator is working correctly.""" - - class ReaderReturn(NamedTuple): - value: bytes - done: bool - - response_mock = mock.Mock() - response_mock._block_size = 5 - response_mock._js_reader.read = mock.Mock() - read_promise = asyncio.Future() - read_promise.set_result(ReaderReturn(value=b"01", done=False)) - reader = mock.Mock() - reader.read.return_value = read_promise - response_mock.js_stream.getReader.return_value = reader - generator = transport.PyodideStreamDownloadGenerator(pipeline=None, response=response_mock) - - assert len(await generator.__anext__()) == response_mock._block_size - assert reader.read.call_count == 3 - assert len(await generator.__anext__()) == response_mock._block_size - # 5 because there is a leftover byte from the previous `__anext__` call. - assert reader.read.call_count == 5 - - read_promise = asyncio.Future() - read_promise.set_result(ReaderReturn(value=None, done=True)) - reader.read.return_value = read_promise - await generator.__anext__() - with pytest.raises(StopAsyncIteration): - await generator.__anext__() - - @pytest.mark.asyncio - async def test_download_generator_compress(self, transport, mock_js_module): - """Test that we are attempting to decompress data when passing the `decompress`.""" - response = mock.Mock() - response.headers = {"enc": "deflate"} - transport.PyodideStreamDownloadGenerator(pipeline=None, response=response, decompress=True) - mock_js_module.DecompressionStream.new.assert_called_once_with("gzip") - def test_valid_import(self, transport): """Test that we can import Pyodide classes from `azure.core.pipeline.transport` Adding the transport fixture will mock the Pyodide modules in `sys.modules`. @@ -209,4 +170,3 @@ def test_valid_import(self, transport): # Use patch so we don't clutter up the `sys.modules` namespace. import azure.core.experimental.transport as transport assert transport.PyodideTransport - assert transport.PyodideTransportResponse From 72ad92042cbcbe1bc5216423c9c74237d774aaf5 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Mon, 19 Sep 2022 16:29:40 -0700 Subject: [PATCH 08/27] update --- .../samples/pyodide_integration/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/core/azure-core-experimental/samples/pyodide_integration/readme.md b/sdk/core/azure-core-experimental/samples/pyodide_integration/readme.md index 5f7ba3adc055..314f29666fb4 100644 --- a/sdk/core/azure-core-experimental/samples/pyodide_integration/readme.md +++ b/sdk/core/azure-core-experimental/samples/pyodide_integration/readme.md @@ -14,7 +14,7 @@ and run python -h http.server ``` -to set up the test server. Then, from a Chromium-based browser such as Edge, go to [`http://localhost:8000/samples/pyodide_integration`](http://localhost:8000/samples/test_pyodide_integration) and the tests will be run in the browser. Dev tip: keep your browser's devtools open. If you make a change to the source code, remember to rebuild your wheel. Note that you might have to update `requirements.txt` depending on the version of `azure-core`. Just make sure the url to `azure-core` in `requirements.txt` matches that of the wheel in `../../dist/`. +to set up the test server. Then, from a Chromium-based browser such as Edge, go to [`http://localhost:8000/samples/pyodide_integration`](http://localhost:8000/samples/pyodide_integration) and the tests will be run in the browser. Dev tip: keep your browser's devtools open. If you make a change to the source code, remember to rebuild your wheel. Note that you might have to update `requirements.txt` depending on the version of `azure-core`. Just make sure the url to `azure-core` in `requirements.txt` matches that of the wheel in `../../dist/`. ## Adding tests From 93545fbd0cd2abec2e9d4d4cba4703f83c8eab1d Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Tue, 20 Sep 2022 12:23:31 -0700 Subject: [PATCH 09/27] update --- eng/ignore-links.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/eng/ignore-links.txt b/eng/ignore-links.txt index 5e57f7127f69..12081cc9ec6e 100644 --- a/eng/ignore-links.txt +++ b/eng/ignore-links.txt @@ -6,3 +6,4 @@ https://docs.microsoft.com/samples/azure-samples/azure-samples-python-management https://pypi.org/project/azure-messaging-webpubsubservice/ https://github.com/Azure/azure-rest-api-specs-pr https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/communication/azure-communication-rooms/samples +http://localhost:8000/samples/pyodide_integration From 878cd019c060ead7d547b87e69a3bee300650f66 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Tue, 20 Sep 2022 14:44:51 -0700 Subject: [PATCH 10/27] update --- eng/.docsettings.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/eng/.docsettings.yml b/eng/.docsettings.yml index f4e9d81bdd17..3e0092e7ad2b 100644 --- a/eng/.docsettings.yml +++ b/eng/.docsettings.yml @@ -149,6 +149,7 @@ known_content_issues: - ['sdk/textanalytics/azure-ai-textanalytics/swagger/README.md', '#4554'] - ['sdk/appconfiguration/azure-appconfiguration/swagger/README.md', '#4554'] - ['sdk/core/azure-core/tests/testserver_tests/coretestserver/README.md', '#4554'] + - ['sdk/core/azure-core-experimental/README.md', '#4554'] package_indexing_exclusion_list: - 'azure-sdk-tools' - 'azure-template' From 37a89e1696110f2302e4cabf07cf207bb4c24b3d Mon Sep 17 00:00:00 2001 From: xiangyan99 Date: Thu, 22 Sep 2022 09:55:44 -0700 Subject: [PATCH 11/27] updates --- .../azure/core/experimental/transport/_pyodide.py | 8 ++++---- .../pyodide_integration/{example-env => example.env} | 0 2 files changed, 4 insertions(+), 4 deletions(-) rename sdk/core/azure-core-experimental/samples/pyodide_integration/{example-env => example.env} (100%) diff --git a/sdk/core/azure-core-experimental/azure/core/experimental/transport/_pyodide.py b/sdk/core/azure-core-experimental/azure/core/experimental/transport/_pyodide.py index f3e51cac5ecf..cb1220a29d63 100644 --- a/sdk/core/azure-core-experimental/azure/core/experimental/transport/_pyodide.py +++ b/sdk/core/azure-core-experimental/azure/core/experimental/transport/_pyodide.py @@ -42,8 +42,8 @@ class PyodideTransportResponse(AsyncHttpResponseImpl): """Async response object for the `PyodideTransport`.""" - @property - def js_stream(self): + + def _js_stream(self): """So we get a fresh stream every time.""" return self._internal_response.clone().js_response.body @@ -73,9 +73,9 @@ def __init__(self, pipeline: Pipeline, response: PyodideTransportResponse, *_, * self.response = response # use this to efficiently store bytes. if kwargs.pop("decompress", False) and self.response.headers.get("enc", None) in ("gzip", "deflate"): - self._js_reader = response.js_stream.pipeThrough(js.DecompressionStream.new("gzip")).getReader() + self._js_reader = response._js_stream().pipeThrough(js.DecompressionStream.new("gzip")).getReader() else: - self._js_reader = response.js_stream.getReader() + self._js_reader = response._js_stream().getReader() self._stream = BytesIO() self._closed = False diff --git a/sdk/core/azure-core-experimental/samples/pyodide_integration/example-env b/sdk/core/azure-core-experimental/samples/pyodide_integration/example.env similarity index 100% rename from sdk/core/azure-core-experimental/samples/pyodide_integration/example-env rename to sdk/core/azure-core-experimental/samples/pyodide_integration/example.env From c2e859f9cfceea3b7bf4a2ce0ca4e31a94bb171b Mon Sep 17 00:00:00 2001 From: xiangyan99 Date: Thu, 22 Sep 2022 09:57:10 -0700 Subject: [PATCH 12/27] update --- sdk/core/azure-core-experimental/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sdk/core/azure-core-experimental/CHANGELOG.md b/sdk/core/azure-core-experimental/CHANGELOG.md index c117570c6fcb..64f2c69bcba5 100644 --- a/sdk/core/azure-core-experimental/CHANGELOG.md +++ b/sdk/core/azure-core-experimental/CHANGELOG.md @@ -2,6 +2,8 @@ ## 1.0.0b1 (Unreleased) +Initial release + ### Features Added - pyodide implementation of azure-core transport protocol From f4fc1244c26ae2356281e172f208262bb83c8fae Mon Sep 17 00:00:00 2001 From: xiangyan99 Date: Thu, 22 Sep 2022 13:16:41 -0700 Subject: [PATCH 13/27] update --- sdk/core/azure-core-experimental/MANIFEST.in | 1 + 1 file changed, 1 insertion(+) diff --git a/sdk/core/azure-core-experimental/MANIFEST.in b/sdk/core/azure-core-experimental/MANIFEST.in index de24585adca7..efb83171670c 100644 --- a/sdk/core/azure-core-experimental/MANIFEST.in +++ b/sdk/core/azure-core-experimental/MANIFEST.in @@ -6,3 +6,4 @@ include azure/core/__init__.py include azure/core/experimental/__init__.py include azure/core/experimental/transport/*.py recursive-include samples *.py +include azure/core/experimental/py.typed From 1b6af197f62326e04185b8f361152f7d1d8a7422 Mon Sep 17 00:00:00 2001 From: xiangyan99 Date: Thu, 22 Sep 2022 14:43:29 -0700 Subject: [PATCH 14/27] updates --- .../dev_requirements.txt | 4 ++- .../samples/pyodide_integration/browser.py | 27 ++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/sdk/core/azure-core-experimental/dev_requirements.txt b/sdk/core/azure-core-experimental/dev_requirements.txt index f9c8d2994225..5c6fe3ccb7db 100644 --- a/sdk/core/azure-core-experimental/dev_requirements.txt +++ b/sdk/core/azure-core-experimental/dev_requirements.txt @@ -1,3 +1,5 @@ -e ../../../tools/azure-sdk-tools ../azure-core --e ../../../tools/azure-devtools \ No newline at end of file +-e ../../../tools/azure-devtools +js +pyodide diff --git a/sdk/core/azure-core-experimental/samples/pyodide_integration/browser.py b/sdk/core/azure-core-experimental/samples/pyodide_integration/browser.py index 545738ae6abe..d91762fbf0d8 100644 --- a/sdk/core/azure-core-experimental/samples/pyodide_integration/browser.py +++ b/sdk/core/azure-core-experimental/samples/pyodide_integration/browser.py @@ -1,4 +1,29 @@ -from unittest.mock import _patch_dict, patch +# -------------------------------------------------------------------------- +# +# 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 uuid import uuid4 from azure.ai.textanalytics.aio import TextAnalyticsClient From 3b8013efe31a4c6266af486b668d20abc2a06572 Mon Sep 17 00:00:00 2001 From: xiangyan99 Date: Thu, 22 Sep 2022 15:15:36 -0700 Subject: [PATCH 15/27] update --- sdk/core/azure-core-experimental/dev_requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/core/azure-core-experimental/dev_requirements.txt b/sdk/core/azure-core-experimental/dev_requirements.txt index 5c6fe3ccb7db..4a0290dd09c3 100644 --- a/sdk/core/azure-core-experimental/dev_requirements.txt +++ b/sdk/core/azure-core-experimental/dev_requirements.txt @@ -2,4 +2,4 @@ ../azure-core -e ../../../tools/azure-devtools js -pyodide +pyodide>=0.19.0a1 From 804ecd4da81b2a865d42dc84baa4ef54552a20ea Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Fri, 23 Sep 2022 14:25:15 -0700 Subject: [PATCH 16/27] Update dev_requirements.txt --- sdk/core/azure-core-experimental/dev_requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/core/azure-core-experimental/dev_requirements.txt b/sdk/core/azure-core-experimental/dev_requirements.txt index 4a0290dd09c3..6bf4d5dae1b9 100644 --- a/sdk/core/azure-core-experimental/dev_requirements.txt +++ b/sdk/core/azure-core-experimental/dev_requirements.txt @@ -2,4 +2,4 @@ ../azure-core -e ../../../tools/azure-devtools js -pyodide>=0.19.0a1 +pyodide --pre From 74bd77c351bb6f54b8d2b12c66d5ce85fb80bbf1 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Mon, 26 Sep 2022 09:33:23 -0700 Subject: [PATCH 17/27] Update dev_requirements.txt --- sdk/core/azure-core-experimental/dev_requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/core/azure-core-experimental/dev_requirements.txt b/sdk/core/azure-core-experimental/dev_requirements.txt index 6bf4d5dae1b9..b1b837da8055 100644 --- a/sdk/core/azure-core-experimental/dev_requirements.txt +++ b/sdk/core/azure-core-experimental/dev_requirements.txt @@ -2,4 +2,4 @@ ../azure-core -e ../../../tools/azure-devtools js -pyodide --pre +pip install pyodide==0.19.0a1 From f4032a6cb3b055862f0649e5dbe1ae0ceb8fd48b Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Mon, 26 Sep 2022 15:41:41 -0700 Subject: [PATCH 18/27] update --- sdk/core/azure-core-experimental/dev_requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/core/azure-core-experimental/dev_requirements.txt b/sdk/core/azure-core-experimental/dev_requirements.txt index b1b837da8055..95ae84a0e430 100644 --- a/sdk/core/azure-core-experimental/dev_requirements.txt +++ b/sdk/core/azure-core-experimental/dev_requirements.txt @@ -2,4 +2,4 @@ ../azure-core -e ../../../tools/azure-devtools js -pip install pyodide==0.19.0a1 +pyodide==0.19.0a1 From 415c943fc34419a6e813caa2f2de50e018f1f087 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Mon, 26 Sep 2022 16:36:16 -0700 Subject: [PATCH 19/27] update --- pylintrc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pylintrc b/pylintrc index 7799d771f6fb..1a1e7abcf55a 100644 --- a/pylintrc +++ b/pylintrc @@ -54,4 +54,7 @@ method-name-hint=lower_case_with_underscores function-name-hint=lower_case_with_underscores argument-name-hint=lower_case_with_underscores variable-name-hint=lower_case_with_underscores -inlinevar-name-hint=lower_case_with_underscores (short is OK) \ No newline at end of file +inlinevar-name-hint=lower_case_with_underscores (short is OK) + +[TYPECHECK] +generated-members=js.* \ No newline at end of file From 6fa3b83bd710b94907efe1fbd225b28501a08440 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Tue, 27 Sep 2022 08:48:05 -0700 Subject: [PATCH 20/27] update --- sdk/core/azure-core-experimental/setup.py | 2 +- shared_requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/core/azure-core-experimental/setup.py b/sdk/core/azure-core-experimental/setup.py index 20ff9ceb5e1c..2dfc82062d89 100644 --- a/sdk/core/azure-core-experimental/setup.py +++ b/sdk/core/azure-core-experimental/setup.py @@ -62,6 +62,6 @@ }, python_requires=">=3.7", install_requires=[ - 'azure-core<2.0.0,>=1.20.0', + 'azure-core<2.0.0,>=1.25.0', ], ) diff --git a/shared_requirements.txt b/shared_requirements.txt index c121ef7ce2a4..8505205d6cbd 100644 --- a/shared_requirements.txt +++ b/shared_requirements.txt @@ -507,4 +507,4 @@ opentelemetry-sdk<2.0.0,>=1.5.0,!=1.10a0 #override azure-mgmt-redis azure-mgmt-core>=1.3.2,<2.0.0 #override azure-mgmt-resourcegraph azure-mgmt-core>=1.3.2,<2.0.0 #override azure-mgmt-resourcegraph msrest>=0.7.1 -#override azure-core-experimental azure-core<2.0.0,>=1.20.0 +#override azure-core-experimental azure-core<2.0.0,>=1.25.0 From 6f1906f40b589cdfd6bb23283e5ed0e3c2d2df69 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Tue, 27 Sep 2022 09:31:59 -0700 Subject: [PATCH 21/27] update --- .../azure-core-experimental/tests/test_pyodide_transport.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sdk/core/azure-core-experimental/tests/test_pyodide_transport.py b/sdk/core/azure-core-experimental/tests/test_pyodide_transport.py index 942f0a4da804..8cbc2bfa3c40 100644 --- a/sdk/core/azure-core-experimental/tests/test_pyodide_transport.py +++ b/sdk/core/azure-core-experimental/tests/test_pyodide_transport.py @@ -146,10 +146,6 @@ async def test_successful_send(self, mock_pyfetch, mock_pyodide_module, pipeline assert kwargs["cert"] is None assert not kwargs["files"] - # check that the js_stream property is cloning - num_clones = mock_pyfetch.clone.call_count - response.js_stream - assert mock_pyfetch.call_count == num_clones + 1 @pytest.mark.asyncio async def test_unsuccessful_send(self, mock_pyfetch, mock_pyodide_module, pipeline): From 752ff7fdc35f096c79c44d57fe63590408643fc0 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Tue, 27 Sep 2022 14:43:30 -0700 Subject: [PATCH 22/27] update --- sdk/core/azure-core-experimental/setup.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sdk/core/azure-core-experimental/setup.py b/sdk/core/azure-core-experimental/setup.py index 2dfc82062d89..d0c02ff16e7b 100644 --- a/sdk/core/azure-core-experimental/setup.py +++ b/sdk/core/azure-core-experimental/setup.py @@ -45,7 +45,6 @@ 'Programming Language :: Python', 'Programming Language :: Python :: 3 :: Only', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', @@ -60,7 +59,7 @@ package_data={ 'pytyped': ['py.typed'], }, - python_requires=">=3.7", + python_requires=">=3.8", install_requires=[ 'azure-core<2.0.0,>=1.25.0', ], From ffc19206f5b78cad4fc763f1b7cfacd7918b2a33 Mon Sep 17 00:00:00 2001 From: xiangyan99 Date: Wed, 28 Sep 2022 13:17:19 -0700 Subject: [PATCH 23/27] updates --- .../core/experimental/transport/__init__.py | 28 ++++++++++--------- sdk/core/azure-core-experimental/setup.py | 3 +- .../tests/test_pyodide_transport.py | 4 ++- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/sdk/core/azure-core-experimental/azure/core/experimental/transport/__init__.py b/sdk/core/azure-core-experimental/azure/core/experimental/transport/__init__.py index 04aef882b0e0..b7d3501810c4 100644 --- a/sdk/core/azure-core-experimental/azure/core/experimental/transport/__init__.py +++ b/sdk/core/azure-core-experimental/azure/core/experimental/transport/__init__.py @@ -23,21 +23,23 @@ # IN THE SOFTWARE. # # -------------------------------------------------------------------------- +import sys # pylint: disable=undefined-all-variable -__all__ = [ - 'PyodideTransport', -] +if sys.version_info >= (3, 7): + __all__ = [ + 'PyodideTransport', + ] -def __dir__(): - return __all__ + def __dir__(): + return __all__ -def __getattr__(name): - if name == 'PyodideTransport': - try: - from ._pyodide import PyodideTransport - return PyodideTransport - except ImportError: - raise ImportError("pyodide package is not installed") - raise AttributeError(f"module 'azure.core.experimental.transport' has no attribute {name}") + def __getattr__(name): + if name == 'PyodideTransport': + try: + from ._pyodide import PyodideTransport + return PyodideTransport + except ImportError: + raise ImportError("pyodide package is not installed") + raise AttributeError(f"module 'azure.core.experimental.transport' has no attribute {name}") diff --git a/sdk/core/azure-core-experimental/setup.py b/sdk/core/azure-core-experimental/setup.py index d0c02ff16e7b..2dfc82062d89 100644 --- a/sdk/core/azure-core-experimental/setup.py +++ b/sdk/core/azure-core-experimental/setup.py @@ -45,6 +45,7 @@ 'Programming Language :: Python', 'Programming Language :: Python :: 3 :: Only', 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', @@ -59,7 +60,7 @@ package_data={ 'pytyped': ['py.typed'], }, - python_requires=">=3.8", + python_requires=">=3.7", install_requires=[ 'azure-core<2.0.0,>=1.25.0', ], diff --git a/sdk/core/azure-core-experimental/tests/test_pyodide_transport.py b/sdk/core/azure-core-experimental/tests/test_pyodide_transport.py index 8cbc2bfa3c40..9dcb5683bf13 100644 --- a/sdk/core/azure-core-experimental/tests/test_pyodide_transport.py +++ b/sdk/core/azure-core-experimental/tests/test_pyodide_transport.py @@ -97,6 +97,7 @@ def create_mock_response( response_promise.set_result(mock_response) return response_promise + @pytest.mark.skipif(sys.version_info < (3, 8)) @pytest.mark.asyncio async def test_successful_send(self, mock_pyfetch, mock_pyodide_module, pipeline): """Test that a successful send returns the correct values.""" @@ -146,7 +147,7 @@ async def test_successful_send(self, mock_pyfetch, mock_pyodide_module, pipeline assert kwargs["cert"] is None assert not kwargs["files"] - + @pytest.mark.skipif(sys.version_info < (3, 8)) @pytest.mark.asyncio async def test_unsuccessful_send(self, mock_pyfetch, mock_pyodide_module, pipeline): """Test that the pipeline is failing correctly.""" @@ -159,6 +160,7 @@ async def test_unsuccessful_send(self, mock_pyfetch, mock_pyodide_module, pipeli # 3 retries plus the original request. assert mock_pyfetch.call_count == retry_total + 1 + @pytest.mark.skipif(sys.version_info < (3, 8)) def test_valid_import(self, transport): """Test that we can import Pyodide classes from `azure.core.pipeline.transport` Adding the transport fixture will mock the Pyodide modules in `sys.modules`. From da79d5b489d954581c19713bfca25b79ab84f5bc Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Thu, 29 Sep 2022 08:31:44 -0700 Subject: [PATCH 24/27] update --- sdk/core/azure-core-experimental/dev_requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/core/azure-core-experimental/dev_requirements.txt b/sdk/core/azure-core-experimental/dev_requirements.txt index 95ae84a0e430..019715d963e1 100644 --- a/sdk/core/azure-core-experimental/dev_requirements.txt +++ b/sdk/core/azure-core-experimental/dev_requirements.txt @@ -2,4 +2,4 @@ ../azure-core -e ../../../tools/azure-devtools js -pyodide==0.19.0a1 +pyodide==0.19.0a1; python_version >= '3.8' From 8279f48bc355c8760bc767623b7356560a2b5095 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Thu, 29 Sep 2022 09:11:25 -0700 Subject: [PATCH 25/27] update --- .../azure-core-experimental/tests/test_pyodide_transport.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/core/azure-core-experimental/tests/test_pyodide_transport.py b/sdk/core/azure-core-experimental/tests/test_pyodide_transport.py index 9dcb5683bf13..7b84222fa908 100644 --- a/sdk/core/azure-core-experimental/tests/test_pyodide_transport.py +++ b/sdk/core/azure-core-experimental/tests/test_pyodide_transport.py @@ -97,7 +97,7 @@ def create_mock_response( response_promise.set_result(mock_response) return response_promise - @pytest.mark.skipif(sys.version_info < (3, 8)) + @pytest.mark.skipif(sys.version_info < (3, 8), reason="pyodide needs py 3.8+") @pytest.mark.asyncio async def test_successful_send(self, mock_pyfetch, mock_pyodide_module, pipeline): """Test that a successful send returns the correct values.""" @@ -147,7 +147,7 @@ async def test_successful_send(self, mock_pyfetch, mock_pyodide_module, pipeline assert kwargs["cert"] is None assert not kwargs["files"] - @pytest.mark.skipif(sys.version_info < (3, 8)) + @pytest.mark.skipif(sys.version_info < (3, 8), reason="pyodide needs py 3.8+") @pytest.mark.asyncio async def test_unsuccessful_send(self, mock_pyfetch, mock_pyodide_module, pipeline): """Test that the pipeline is failing correctly.""" @@ -160,7 +160,7 @@ async def test_unsuccessful_send(self, mock_pyfetch, mock_pyodide_module, pipeli # 3 retries plus the original request. assert mock_pyfetch.call_count == retry_total + 1 - @pytest.mark.skipif(sys.version_info < (3, 8)) + @pytest.mark.skipif(sys.version_info < (3, 8), reason="pyodide needs py 3.8+") def test_valid_import(self, transport): """Test that we can import Pyodide classes from `azure.core.pipeline.transport` Adding the transport fixture will mock the Pyodide modules in `sys.modules`. From 398cc376818177bd1996d1aed9a86fa29209f522 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Sun, 2 Oct 2022 11:05:42 -0700 Subject: [PATCH 26/27] update --- .../azure/core/experimental/__init__.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/sdk/core/azure-core-experimental/azure/core/experimental/__init__.py b/sdk/core/azure-core-experimental/azure/core/experimental/__init__.py index 35bb7b7a2fb1..a5db9f961fc2 100644 --- a/sdk/core/azure-core-experimental/azure/core/experimental/__init__.py +++ b/sdk/core/azure-core-experimental/azure/core/experimental/__init__.py @@ -1,2 +1,28 @@ +# -------------------------------------------------------------------------- +# +# 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 ba0f1a90270d77f698117837575d5be9ef0691e6 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Mon, 3 Oct 2022 11:50:10 -0700 Subject: [PATCH 27/27] Update CHANGELOG.md --- sdk/core/azure-core-experimental/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/core/azure-core-experimental/CHANGELOG.md b/sdk/core/azure-core-experimental/CHANGELOG.md index 64f2c69bcba5..31ec168df3b6 100644 --- a/sdk/core/azure-core-experimental/CHANGELOG.md +++ b/sdk/core/azure-core-experimental/CHANGELOG.md @@ -1,6 +1,6 @@ # Release History -## 1.0.0b1 (Unreleased) +## 1.0.0b1 (2022-10-06) Initial release