140 lines
5.6 KiB
Diff
140 lines
5.6 KiB
Diff
diff --git a/awscli/arguments.py b/awscli/arguments.py
|
|
index 77639cf..3ab060b 100644
|
|
--- a/awscli/arguments.py
|
|
+++ b/awscli/arguments.py
|
|
@@ -451,7 +451,7 @@ class CLIArgument(BaseCLIArgument):
|
|
cli_name = self.cli_name
|
|
parser.add_argument(
|
|
cli_name,
|
|
- help=self.documentation,
|
|
+ help=self.documentation.replace("%", "%%"),
|
|
type=self.cli_type,
|
|
required=self.required,
|
|
)
|
|
@@ -602,7 +602,7 @@ class BooleanArgument(CLIArgument):
|
|
def add_to_parser(self, parser):
|
|
parser.add_argument(
|
|
self.cli_name,
|
|
- help=self.documentation,
|
|
+ help=self.documentation.replace("%", "%%"),
|
|
action=self._action,
|
|
default=self._default,
|
|
dest=self._destination,
|
|
diff --git a/awscli/customizations/logs/startlivetail.py b/awscli/customizations/logs/startlivetail.py
|
|
index cc5849b..bc71a3d 100644
|
|
--- a/awscli/customizations/logs/startlivetail.py
|
|
+++ b/awscli/customizations/logs/startlivetail.py
|
|
@@ -833,7 +833,7 @@ class InteractiveUI(BaseLiveTailUI):
|
|
await self._application.run_async()
|
|
|
|
def run(self):
|
|
- asyncio.get_event_loop().run_until_complete(self._run_ui())
|
|
+ asyncio.run(self._run_ui())
|
|
|
|
|
|
class PrintOnlyPrinter(BaseLiveTailPrinter):
|
|
diff --git a/awscli/customizations/wizard/app.py b/awscli/customizations/wizard/app.py
|
|
index c813b97..028fcaa 100644
|
|
--- a/awscli/customizations/wizard/app.py
|
|
+++ b/awscli/customizations/wizard/app.py
|
|
@@ -10,9 +10,9 @@
|
|
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
|
# ANY KIND, either express or implied. See the License for the specific
|
|
# language governing permissions and limitations under the License.
|
|
+import asyncio
|
|
import json
|
|
import os
|
|
-from asyncio import new_event_loop, set_event_loop
|
|
from collections.abc import MutableMapping
|
|
|
|
from prompt_toolkit.application import Application
|
|
@@ -77,14 +77,12 @@ class WizardApp(Application):
|
|
)
|
|
|
|
def run(self, pre_run=None, **kwargs):
|
|
- loop = new_event_loop()
|
|
- try:
|
|
- set_event_loop(loop)
|
|
+ def create_event_loop():
|
|
+ loop = asyncio.new_event_loop()
|
|
loop.set_exception_handler(self._handle_exception)
|
|
- f = self.run_async(pre_run=pre_run, set_exception_handler=False)
|
|
- return loop.run_until_complete(f)
|
|
- finally:
|
|
- loop.close()
|
|
+ return loop
|
|
+ f = self.run_async(pre_run=pre_run, set_exception_handler=False)
|
|
+ return asyncio.run(f, loop_factory=create_event_loop)
|
|
|
|
def _handle_exception(self, loop, context):
|
|
self.exit(exception=UnexpectedWizardException(context['exception']))
|
|
diff --git a/tests/__init__.py b/tests/__init__.py
|
|
index db70912..0ab2e4a 100644
|
|
--- a/tests/__init__.py
|
|
+++ b/tests/__init__.py
|
|
@@ -471,16 +471,9 @@ class PromptToolkitAppRunner:
|
|
# This is the function that will be passed to our thread to
|
|
# actually run the application
|
|
try:
|
|
- # When we run the app in a separate thread, there is no
|
|
- # default event loop. This ensures we create one as it is
|
|
- # likely the application will try to grab the default loop
|
|
- loop = asyncio.new_event_loop()
|
|
- asyncio.set_event_loop(loop)
|
|
app_run_context.return_value = target(*target_args)
|
|
except BaseException as e:
|
|
app_run_context.raised_exception = e
|
|
- finally:
|
|
- loop.close()
|
|
|
|
def _wait_until_app_is_done_updating(self):
|
|
self._wait_until_app_is_done_rendering()
|
|
diff --git a/tests/functional/test_utils.py b/tests/functional/test_utils.py
|
|
--- a/tests/functional/test_utils.py
|
|
+++ b/tests/functional/test_utils.py
|
|
@@ -18,7 +18,7 @@ class TestWriteException(unittest.TestCa
|
|
def test_write_exception(self):
|
|
error_message = "Some error message."
|
|
ex = Exception(error_message)
|
|
- with codecs.open(self.outfile, 'w+', encoding='utf-8') as outfile:
|
|
+ with open(self.outfile, 'w+', encoding='utf-8') as outfile:
|
|
write_exception(ex, outfile)
|
|
outfile.seek(0)
|
|
|
|
diff --git a/tests/unit/botocore/test_utils.py b/tests/unit/botocore/test_utils.py
|
|
--- a/tests/unit/botocore/test_utils.py
|
|
+++ b/tests/unit/botocore/test_utils.py
|
|
@@ -3646,20 +3646,28 @@ def test_lru_cache_weakref():
|
|
cls2 = ClassWithCachedMethod()
|
|
|
|
assert cls1.cached_fn.cache_info().currsize == 0
|
|
- assert getrefcount(cls1) == 2
|
|
- assert getrefcount(cls2) == 2
|
|
+ refcount1 = getrefcount(cls1)
|
|
+ refcount2 = getrefcount(cls2)
|
|
+ assert refcount1 in (1, 2)
|
|
+ assert refcount2 in (1, 2)
|
|
# "The count returned is generally one higher than you might expect, because
|
|
# it includes the (temporary) reference as an argument to getrefcount()."
|
|
# https://docs.python.org/3.8/library/sys.html#getrefcount
|
|
|
|
+ # However, as of 3.14: "The interpreter internally avoids some reference
|
|
+ # count modifications when loading objects onto the operands stack by
|
|
+ # borrowing references when possible. This can lead to smaller reference
|
|
+ # count values compared to previous Python versions."
|
|
+ # https://docs.python.org/3.14/whatsnew/3.14.html#whatsnew314-refcount
|
|
+
|
|
cls1.cached_fn(1, 1)
|
|
cls2.cached_fn(1, 1)
|
|
|
|
# The cache now has two entries, but the reference count remains the same as
|
|
# before.
|
|
assert cls1.cached_fn.cache_info().currsize == 2
|
|
- assert getrefcount(cls1) == 2
|
|
- assert getrefcount(cls2) == 2
|
|
+ assert getrefcount(cls1) == refcount1
|
|
+ assert getrefcount(cls2) == refcount2
|
|
|
|
# Deleting one of the objects does not interfere with the cache entries
|
|
# related to the other object.
|