Update zaza/__init__.py from zaza (#750)
The zaza and zaza-openstack-tests project are currently installed within the same package. A side effect of that is that the zaza/__init__.py from zaza is overwritten by the one in zaza-openstack-tests. We ought to find a better way of doing this but we're currently blocked on using zaza + zaza-openstack-tests on systems with Python 3.10 installed, and updating this file unblocks us. Update zaza/__init__.py from openstack-charmers/zaza@c48c955ef7
This commit is contained in:
+63
-3
@@ -12,9 +12,27 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# __NOTE__
|
||||
#
|
||||
# Whenever this file is changed, make sure to update the copy of it in
|
||||
# ``zaza-openstack-tests``.
|
||||
#
|
||||
# The ``zaza`` and ``zaza-openstack-tests`` projects are related, and currently
|
||||
# the latter is installed as a package inside the former. As a consequence
|
||||
# ``zaza-openstack-tests`` needs to carry a copy of this file
|
||||
# (``zaza/__init__.py``) as this file will be overwritten by the copy in
|
||||
# ``zaza-openstack-tests`` on install.
|
||||
#
|
||||
# We of course want a better solution to this, but in the interest of time
|
||||
# this note is left here until we get around to fixing it properly.
|
||||
#
|
||||
# __NOTE__
|
||||
|
||||
"""Functions to support converting async function to a sync equivalent."""
|
||||
import asyncio
|
||||
import logging
|
||||
from pkgutil import extend_path
|
||||
from sys import version_info
|
||||
|
||||
|
||||
__path__ = extend_path(__path__, __name__)
|
||||
@@ -23,22 +41,64 @@ __path__ = extend_path(__path__, __name__)
|
||||
def run(*steps):
|
||||
"""Run the given steps in an asyncio loop.
|
||||
|
||||
:returns: The result of the asyncio.Task
|
||||
If the tasks spawns other future (tasks) then these are also cleaned up
|
||||
after each step is performed.
|
||||
|
||||
:returns: The result of the last asyncio.Task
|
||||
:rtype: Any
|
||||
"""
|
||||
if not steps:
|
||||
return
|
||||
loop = asyncio.get_event_loop()
|
||||
try:
|
||||
loop = asyncio.get_running_loop()
|
||||
except RuntimeError:
|
||||
loop = asyncio.new_event_loop()
|
||||
except AttributeError:
|
||||
# Remove once support for Python 3.6 is dropped
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
for step in steps:
|
||||
task = loop.create_task(step)
|
||||
loop.run_until_complete(asyncio.wait([task], loop=loop))
|
||||
loop.run_until_complete(asyncio.wait([task]))
|
||||
|
||||
# Let's also cancel any remaining tasks:
|
||||
while True:
|
||||
# issue #445 - asyncio.Task.all_tasks() deprecated in 3.7
|
||||
if version_info.major == 3 and version_info.minor >= 7:
|
||||
try:
|
||||
tasklist = asyncio.all_tasks()
|
||||
except RuntimeError:
|
||||
# no running event loop
|
||||
break
|
||||
else:
|
||||
tasklist = asyncio.Task.all_tasks()
|
||||
pending_tasks = [p for p in tasklist if not p.done()]
|
||||
if pending_tasks:
|
||||
logging.info(
|
||||
"async -> sync. cleaning up pending tasks: len: {}"
|
||||
.format(len(pending_tasks)))
|
||||
for pending_task in pending_tasks:
|
||||
pending_task.cancel()
|
||||
try:
|
||||
loop.run_until_complete(pending_task)
|
||||
except asyncio.CancelledError:
|
||||
pass
|
||||
except Exception as e:
|
||||
logging.error(
|
||||
"A pending task caused an exception: {}"
|
||||
.format(str(e)))
|
||||
else:
|
||||
break
|
||||
|
||||
return task.result()
|
||||
|
||||
|
||||
def sync_wrapper(f):
|
||||
"""Convert the given async function into a sync function.
|
||||
|
||||
This is only to be called from sync code and it runs all tasks (and cancels
|
||||
all tasks at the end of each run) for the code that is being given.
|
||||
|
||||
:returns: The de-async'd function
|
||||
:rtype: function
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user