зеркало из
1
0
Форкнуть 0
This commit is contained in:
Carter Tinney 2024-02-12 10:55:22 -08:00 коммит произвёл GitHub
Родитель 210cb0b068
Коммит 05e049d976
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
33 изменённых файлов: 9 добавлений и 365 удалений

Просмотреть файл

@ -1,6 +1,6 @@
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.192.0/containers/python-3/.devcontainer/base.Dockerfile
# [Choice] Python version: 3, 3.9, 3.8, 3.7, 3.6
# [Choice] Python version: 3, 3.9, 3.8, 3.7
ARG VARIANT="3.9"
FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT}

Просмотреть файл

@ -6,7 +6,7 @@
"dockerfile": "Dockerfile",
"context": "..",
"args": {
// Update 'VARIANT' to pick a Python version: 3, 3.6, 3.7, 3.8, 3.9
// Update 'VARIANT' to pick a Python version: 3, 3.7, 3.8, 3.9
"VARIANT": "3",
// Options
"NODE_VERSION": "lts/*"

Просмотреть файл

@ -5,10 +5,10 @@
# --------------------------------------------------------------------------
"""This module contains tools for adapting sync code for use in async coroutines."""
import asyncio
import functools
import logging
import traceback
import azure.iot.device.common.asyncio_compat as asyncio_compat
logger = logging.getLogger(__name__)
@ -25,7 +25,7 @@ def emulate_async(fn):
@functools.wraps(fn)
async def async_fn_wrapper(*args, **kwargs):
loop = asyncio_compat.get_running_loop()
loop = asyncio.get_running_loop()
# Run fn in default ThreadPoolExecutor (CPU * 5 threads)
return await loop.run_in_executor(None, functools.partial(fn, *args, **kwargs))
@ -44,7 +44,7 @@ class AwaitableCallback(object):
if return_arg_name and not isinstance(return_arg_name, str):
raise TypeError("internal error: return_arg_name must be a string")
loop = asyncio_compat.get_running_loop()
loop = asyncio.get_running_loop()
self.future = loop.create_future()
def wrapping_callback(*args, **kwargs):

Просмотреть файл

@ -1,61 +0,0 @@
# -------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for
# license information.
# --------------------------------------------------------------------------
"""This module contains compatibility tools for bridging different versions of asyncio"""
import asyncio
import sys
def get_running_loop():
"""Gets the currently running event loop
Uses asyncio.get_running_loop() if available (Python 3.7+) or a back-ported
version of the same function in 3.6.
"""
try:
loop = asyncio.get_running_loop()
except AttributeError:
loop = asyncio._get_running_loop()
if loop is None:
raise RuntimeError("no running event loop")
return loop
def create_task(coro):
"""Creates a Task object.
If available (Python 3.7+), use asyncio.create_task, which is preferred as it is
more specific for the goal of immediately scheduling a task from a coroutine. If
not available, use the more general purpose asyncio.ensure_future.
:returns: A new Task object.
"""
try:
task = asyncio.create_task(coro)
except AttributeError:
task = asyncio.ensure_future(coro)
return task
def run(coro):
"""Execute the coroutine coro and return the result.
It creates a new event loop and closes it at the end.
Cannot be called when another asyncio event loop is running in the same thread.
If available (Python 3.7+) use asyncio.run. If not available, use a custom implementation
that achieves the same thing
"""
if sys.version_info >= (3, 7):
return asyncio.run(coro)
else:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
return loop.run_until_complete(coro)
finally:
loop.close()
asyncio.set_event_loop(None)

Просмотреть файл

@ -1,6 +1,6 @@
pytest < 8.0.0 # lazy_fixture currently broken in 8
pytest < 8.0.0
pytest-asyncio <= 0.16
pytest-mock
pytest-asyncio <= 0.16 # Can remove this once Python 3.6 support is dropped
pytest-testdox>=1.1.1
pytest-cov
pytest-timeout

Просмотреть файл

@ -4,17 +4,6 @@ This directory contains samples showing how to use the various features of Azure
**Please note** that IoT Edge solutions are scoped to Linux containers and devices, documented [here](https://docs.microsoft.com/en-us/azure/iot-edge/tutorial-python-module#solution-scope). Please see [this blog post](https://techcommunity.microsoft.com/t5/internet-of-things/linux-modules-with-azure-iot-edge-on-windows-10-iot-enterprise/ba-p/1407066) to learn more about using Linux containers for IoT Edge on Windows devices.
**These samples are written to run in Python 3.7+**, but can be made to work with Python 3.6 with a slight modification as noted in each sample:
```python
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()
```
In order to use these samples, they **must** be run from inside an Edge container.

Просмотреть файл

@ -34,8 +34,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -37,8 +37,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -51,8 +51,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -38,8 +38,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -27,8 +27,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -2,17 +2,6 @@
This directory contains samples showing how to use the various features of Azure IoT Hub Device SDK with the Azure IoT Hub.
**These samples are written to run in Python 3.7+**, but can be made to work with Python 3.6 with a slight modification as noted in each sample:
```python
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()
```
## Included Samples

Просмотреть файл

@ -27,8 +27,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -60,8 +60,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -131,8 +131,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -70,8 +70,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -66,8 +66,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -64,8 +64,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -52,8 +52,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -60,8 +60,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -47,8 +47,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -43,8 +43,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -29,8 +29,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -55,8 +55,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -49,8 +49,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -53,8 +53,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -28,8 +28,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -68,8 +68,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -335,8 +335,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -417,8 +417,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -30,8 +30,3 @@ async def main():
if __name__ == "__main__":
asyncio.run(main())
# If using Python 3.6 use the following code instead of asyncio.run(main()):
# loop = asyncio.get_event_loop()
# loop.run_until_complete(main())
# loop.close()

Просмотреть файл

@ -1,146 +0,0 @@
# -------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for
# license information.
# --------------------------------------------------------------------------
import pytest
import asyncio
import sys
import logging
from azure.iot.device.common import asyncio_compat
logging.basicConfig(level=logging.DEBUG)
pytestmark = pytest.mark.asyncio
@pytest.mark.describe("get_running_loop()")
class TestGetRunningLoop(object):
@pytest.mark.it("Returns the currently running Event Loop in Python 3.7 or higher")
@pytest.mark.skipif(sys.version_info < (3, 7), reason="Requires Python 3.7+")
async def test_returns_currently_running_event_loop_(self, mocker, event_loop):
spy_get_running_loop = mocker.spy(asyncio, "get_running_loop")
result = asyncio_compat.get_running_loop()
assert result == event_loop
assert spy_get_running_loop.call_count == 1
assert spy_get_running_loop.call_args == mocker.call()
@pytest.mark.it(
"Raises a RuntimeError if there is no running Event Loop in Python 3.7 or higher"
)
@pytest.mark.skipif(sys.version_info < (3, 7), reason="Requires Python 3.7+")
async def test_raises_runtime_error_if_no_running_event_loop(self, mocker):
mocker.patch.object(asyncio, "get_running_loop", side_effect=RuntimeError)
with pytest.raises(RuntimeError):
asyncio_compat.get_running_loop()
@pytest.mark.it("Returns the currently running Event Loop in Python 3.6")
@pytest.mark.skipif(sys.version_info >= (3, 7), reason="Requires Python 3.6")
async def test_returns_currently_running_event_loop_py36orless_compat(self, mocker, event_loop):
spy_get_event_loop = mocker.spy(asyncio, "_get_running_loop")
result = asyncio_compat.get_running_loop()
assert result == event_loop
assert spy_get_event_loop.call_count == 1
assert spy_get_event_loop.call_args == mocker.call()
@pytest.mark.it("Raises a RuntimeError if there is no running Event Loop in Python 3.6")
@pytest.mark.skipif(sys.version_info >= (3, 7), reason="Requires Python 3.6")
async def test_raises_runtime_error_if_no_running_event_loop_py36orless_compat(self, mocker):
mocker.patch.object(asyncio, "_get_running_loop", return_value=None)
with pytest.raises(RuntimeError):
asyncio_compat.get_running_loop()
@pytest.mark.describe("create_task()")
class TestCreateTask(object):
@pytest.fixture
def dummy_coroutine(self):
async def coro():
return
return coro
@pytest.mark.it(
"Returns a Task that wraps a given coroutine, and schedules its execution, in Python 3.7 or higher"
)
@pytest.mark.skipif(sys.version_info < (3, 7), reason="Requires Python 3.7+")
async def test_returns_task_wrapping_given_coroutine(self, mocker, dummy_coroutine):
spy_create_task = mocker.spy(asyncio, "create_task")
coro_obj = dummy_coroutine()
result = asyncio_compat.create_task(coro_obj)
assert isinstance(result, asyncio.Task)
assert spy_create_task.call_count == 1
assert spy_create_task.call_args == mocker.call(coro_obj)
@pytest.mark.it(
"Returns a Task that wraps a given coroutine, and schedules its execution, in Python 3.6"
)
@pytest.mark.skipif(sys.version_info >= (3, 7), reason="Requires Python 3.6")
async def test_returns_task_wrapping_given_coroutine_py36orless_compat(
self, mocker, dummy_coroutine
):
spy_ensure_future = mocker.spy(asyncio, "ensure_future")
coro_obj = dummy_coroutine()
result = asyncio_compat.create_task(coro_obj)
assert isinstance(result, asyncio.Task)
assert spy_ensure_future.call_count == 1
assert spy_ensure_future.call_args == mocker.call(coro_obj)
@pytest.mark.describe("run()")
class TestRun(object):
@pytest.mark.it("Runs the given coroutine on a new event loop in Python 3.7 or higher")
@pytest.mark.skipif(sys.version_info < (3, 7), reason="Requires Python 3.7+")
def test_run_37_or_greater(self, mocker):
mock_asyncio_run = mocker.patch.object(asyncio, "run")
mock_coro = mocker.MagicMock()
result = asyncio_compat.run(mock_coro)
assert mock_asyncio_run.call_count == 1
assert mock_asyncio_run.call_args == mocker.call(mock_coro)
assert result == mock_asyncio_run.return_value
@pytest.mark.it("Runs the given coroutine on a new event loop in Python 3.6")
@pytest.mark.skipif(sys.version_info >= (3, 7), reason="Requires Python 3.6")
def test_run_36orless_compat(self, mocker):
mock_new_event_loop = mocker.patch.object(asyncio, "new_event_loop")
mock_set_event_loop = mocker.patch.object(asyncio, "set_event_loop")
mock_loop = mock_new_event_loop.return_value
mock_coro = mocker.MagicMock()
result = asyncio_compat.run(mock_coro)
# New event loop was created and set
assert mock_new_event_loop.call_count == 1
assert mock_new_event_loop.call_args == mocker.call()
assert mock_set_event_loop.call_count == 2 # (second time at the end)
assert mock_set_event_loop.call_args_list[0] == mocker.call(mock_loop)
# Coroutine was run on the event loop, with the result returned
assert mock_loop.run_until_complete.call_count == 1
assert mock_loop.run_until_complete.call_args == mocker.call(mock_coro)
assert result == mock_loop.run_until_complete.return_value
# Loop was closed after completion
assert mock_loop.close.call_count == 1
assert mock_loop.close.call_args == mocker.call()
# Event loop was set back to None
assert mock_set_event_loop.call_args_list[1] == mocker.call(None)
@pytest.mark.it(
"Closes the event loop and resets to None, even if an error occurs running the coroutine, in Python 3.6"
)
@pytest.mark.skipif(sys.version_info >= (3, 7), reason="Requires Python 3.6")
def test_error_running_36orless_compat(self, mocker, arbitrary_exception):
# NOTE: This test is not necessary for 3.7 because asyncio.run() does this for us
mock_new_event_loop = mocker.patch.object(asyncio, "new_event_loop")
mock_set_event_loop = mocker.patch.object(asyncio, "set_event_loop")
mock_loop = mock_new_event_loop.return_value
mock_loop.run_until_complete.side_effect = arbitrary_exception
mock_coro = mocker.MagicMock()
with pytest.raises(type(arbitrary_exception)):
asyncio_compat.run(mock_coro)
assert mock_loop.close.call_count == 1
assert mock_set_event_loop.call_count == 2 # Once set, once to unset
assert mock_set_event_loop.call_args_list[0] == mocker.call(mock_loop)
assert mock_set_event_loop.call_args_list[1] == mocker.call(None)

Просмотреть файл

@ -6,7 +6,6 @@
import logging
import pytest
import pytest_asyncio
import asyncio
import time
import urllib
@ -47,12 +46,6 @@ from ..shared_client_tests import (
pytestmark = pytest.mark.asyncio
logging.basicConfig(level=logging.DEBUG)
# Python 3.6 only supports pytest_asyncio==0.16.0 which doesn't have pytest_asyncio.fixture.
try:
asyncio_fixture = pytest_asyncio.fixture
except AttributeError:
asyncio_fixture = pytest.fixture
async def create_completed_future(result=None):
f = asyncio.Future()
@ -1259,7 +1252,7 @@ class IoTHubDeviceClientTestsConfig(object):
def client_class(self):
return IoTHubDeviceClient
@asyncio_fixture
@pytest.fixture
async def client(self, mqtt_pipeline, http_pipeline):
"""This client automatically resolves callbacks sent to the pipeline.
It should be used for the majority of tests.
@ -1781,7 +1774,7 @@ class IoTHubModuleClientTestsConfig(object):
def client_class(self):
return IoTHubModuleClient
@asyncio_fixture
@pytest.fixture
async def client(self, mqtt_pipeline, http_pipeline):
"""This client automatically resolves callbacks sent to the pipeline.
It should be used for the majority of tests.